Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pabloeferreyra/Turnero/llms.txt

Use this file to discover all available pages before exploring further.

Turnero uses ASP.NET Core SignalR to broadcast appointment changes to every connected browser the moment they happen. Rather than polling the server on a timer, clinic reception staff and doctors receive an instant notification whenever a turn is booked, accessed, edited, or deleted — and the appointment DataTable on screen refreshes automatically. No browser extension or third-party push service is required.

How SignalR Is Registered

SignalR is added with the JSON protocol and mapped to its hub route in Program.cs:
// Service registration
builder.Services.AddSignalR()
    .AddJsonProtocol();

// Route mapping (after app.UseAuthorization())
app.MapHub<TurnsTableHub>("/TurnsTableHub");
The JSON protocol means all hub messages are serialised as JSON, making them straightforward to consume from any JavaScript client.

TurnsTableHub Methods

TurnsTableHub exposes two server-side methods that Turnero’s service layer calls when appointment state changes:
public class TurnsTableHub : Hub
{
    // Send a message to a single connected user identified by their userId
    public async Task UpdateTableDirected(string user, string message, string date)
    {
        await Clients.User(user).SendAsync(message, date);
    }

    // Broadcast a message to every connected client
    public async Task UpdateTable(string message)
    {
        await Clients.All.SendAsync(message);
    }
}
MethodTargetWhen to use
UpdateTableDirectedA single user by ASP.NET Identity user IDNotify a specific doctor or the Ingreso role users
UpdateTableAll connected clientsBroadcast deletions or global state changes
Clients.User(userId) resolves the target connection using ASP.NET Core’s built-in IUserIdProvider, which maps the authenticated ClaimsPrincipalNameIdentifier claim (the ASP.NET Identity user ID) to open WebSocket connections. A doctor must be currently logged in for directed notifications to reach their browser.

When Turnero Pushes Updates

The service layer calls hub methods via IHubContext<TurnsTableHub> in response to four events:
EventHub callRecipients
New appointment createdUpdateTableDirected(doctorUserId, message, date)The assigned doctor only
Appointment marked as AccessedUpdateTableDirected(userId, message, date)All users in the Ingreso role
Appointment editedUpdateTableDirected(userId, message, date)All users in the Ingreso role
Appointment deletedUpdateTable(message)All connected clients
This means a doctor’s browser updates silently when a new turn is booked for them, while reception staff (Ingreso role) see live updates for accessed and edited turns, and every open session reflects deletions immediately.

Client-Side Setup

Add the SignalR JavaScript client from the CDN or your bundled assets, then connect to the hub and register listeners for both message types:
<script src="~/lib/microsoft/signalr/dist/browser/signalr.min.js"></script>
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/TurnsTableHub")
    .build();

// Broadcast handler — fires on appointment deletion
connection.on("UpdateTable", function (message) {
    // Reload the DataTable without a full page refresh
    turnsTable.ajax.reload();
});

// Directed handler — fires on create, access, and edit events
connection.on("UpdateTableDirected", function (medicName, message, date) {
    // Show a toast notification with context
    showNotification(medicName, message);
    turnsTable.ajax.reload();
});

connection.start().catch(err => console.error(err));
Use .withAutomaticReconnect() on the HubConnectionBuilder to handle brief network interruptions gracefully without requiring a page reload:
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/TurnsTableHub")
    .withAutomaticReconnect()
    .build();

CORS Configuration

Turnero’s middleware pipeline configures CORS before authentication runs, permitting any origin to connect:
app.UseCors(policy => policy
    .AllowAnyOrigin()
    .AllowAnyMethod()
    .AllowAnyHeader());
This allows SignalR connections from different origins (for example, a separate front-end application or a mobile WebView). If you want to restrict access to known clinic domains, replace AllowAnyOrigin() with WithOrigins("https://clinic.example").
AllowAnyOrigin combined with AllowCredentials is not supported by the browser security model. Turnero does not call AllowCredentials, so the broad origin policy is valid — but be aware that cookie-based authentication requires same-origin requests; only the JWT bearer path works cross-origin.

Troubleshooting

SymptomLikely causeFix
Directed notifications never arriveDoctor is not logged inEnsure the target user has an active authenticated session
UpdateTableDirected fires but the DataTable does not reloadEvent name mismatchConfirm the string passed to SendAsync matches the name registered in connection.on(...)
WebSocket connection refused in browser consoleHTTPS not configured in developmentRun with dotnet run --launch-profile https or trust the dev certificate with dotnet dev-certs https --trust
Hub disconnects after idle periodReverse-proxy timeoutIncrease the proxy’s WebSocket timeout (e.g. proxy_read_timeout 3600 in Nginx)

Build docs developers (and LLMs) love