API Routes (tRPC)
The entire backend API is built using tRPC, providing end-to-end typesafe APIs. All API logic is located in src/server/routers/. This document details each procedure and its role within the application.
Structure
The API is namespaced into logical routers:
auth: Handles initial setup and authentication checks.campaign: Manages the lifecycle of campaigns and their poll links.poll: Handles public-facing interactions for voting.results: Provides aggregated data for the results dashboard.
Procedures are either protectedProcedure (requiring an authenticated user) or procedure (public).
authRouter
auth.canRegister
- Type:
Query - Access: Public
- Description: Checks if any user exists in the database. This is a critical security and UX feature.
- Frontend Usage: Called by
LoginForm.tsxusing thepublicTrpcclient. The result determines if the "Sign Up" tab is rendered, effectively allowing registration only for the very first administrator. - Input:
void - Output:
{ canRegister: boolean; }
campaignRouter
campaign.list
- Type:
Query - Access: Protected
- Description: Retrieves all campaigns for the logged-in user, including aggregated stats. It has a side effect of auto-archiving any campaigns whose expiration date has passed.
- Frontend Usage: This is the main data source for the
ActiveCampaignsPage.tsx. The fetched data populates the campaigns table, showing name, vote counts, participation rates, etc. - Input:
void - Output:
Array<{ id: number; name: string; managerCount: number; ... }>
campaign.getLinks
- Type:
Query - Access: Protected
- Description: Fetches all poll links for a single, specified campaign.
- Frontend Usage: Called conditionally in
ActiveCampaignsPage.tsxwhen the user opens the "Manage Links" dialog. The query is enabled only when aselectedCampaignIdis set. - Input:
number(ThecampaignId) - Output:
Array<{ id: string; managerName: string; url: string; }>
campaign.addManager
- Type:
Mutation - Access: Protected
- Description: Adds a new manager and a unique poll link to an existing campaign.
- Frontend Usage: Called from the "Add Manager" dialog within
ActiveCampaignsPage.tsx. On success, it invalidates thecampaign.listandcampaign.getLinksqueries viauseUtilsto ensure the UI updates instantly. - Input:
{ campaignId: number; managerName: string; } - Output:
{ id: string; managerName: string; url: string; }
campaign.setArchiveStatus
- Type:
Mutation - Access: Protected
- Description: Toggles the
archivedstatus of a campaign. - Frontend Usage: Called from the "Archive"/"Restore" action in the
DropdownMenuon theActiveCampaignsPage.tsx. On success, it invalidates thecampaign.listquery to refresh the table. - Input:
{ campaignId: number; archived: boolean; } - Output:
{ success: boolean; archived: boolean; }
campaign.create
- Type:
Mutation - Access: Protected
- Description: Creates a new campaign and batch-creates all its initial poll links.
- Frontend Usage: This is the core mutation on
NewCampaignPage.tsx. On success, it returns the generated links, which causes the UI to switch from the form view to the results view displaying the new links. - Input:
{ name: string; managers: string[]; expiresAt?: Date; } - Output:
{ campaignId: number; campaignName: string; generatedLinks: Array<{...}> }
pollRouter
poll.getInfoByToken
- Type:
Query - Access: Public
- Description: Retrieves the public-facing name of a campaign and manager for a given poll token.
- Frontend Usage: Called on
PollClientPage.tsxusing thepublicTrpcclient. The result is used to display context to the user (e.g., "Poll for John Doe's team (Campaign: Q4 Feedback)"). If the query fails, the user is redirected to the/poll/closedpage. - Input:
string(ThepollToken) - Output:
{ managerName: string; campaignName: string; }
poll.submitVote
- Type:
Mutation - Access: Public
- Description: Records a new vote for a given poll.
- Frontend Usage: The main action on
PollClientPage.tsx. It is called when the user submits the form. On success, it provides feedback via a toast notification. - Input:
{ pollToken: string; mood: "green" | "blue" | ...; comment?: string; } - Output:
{ message: string; voteId: number; }
resultsRouter
results.getCampaignOptions
- Type:
Query - Access: Protected
- Description: Fetches a simplified list of the user's campaigns.
- Frontend Usage: Used on the
GlobalResultsClientpage to populate the campaign selection dropdown in theFilterBarcomponent. - Input:
void - Output:
Array<{ id: number; name: string; }>
results.getManagerOptions
- Type:
Query - Access: Protected
- Description: Fetches a distinct list of manager names based on the selected campaign(s).
- Frontend Usage: Used on the
GlobalResultsClientpage to populate the manager selection dropdown in theFilterBar. The list dynamically updates when the campaign filter is changed. - Input:
{ campaignId: number | "all"; } - Output:
Array<string>
results.getFilteredResults
- Type:
Query - Access: Protected
- Description: The main data-aggregation endpoint for the dashboard. It fetches and processes votes based on campaign, manager, and date filters.
- Frontend Usage: This is the primary data source for
GlobalResultsClient. The extensive output object provides all the necessary data to render theMoodChart,CommentsList, andStatsCardscomponents. - Input:
{ campaignId: number | "all"; managerName: string | "all"; dateRange: {...}; } - Output: A large object containing
totalVotes,moodDistribution,comments, etc.