Improve admin candidate modal UX and add clip menu visibility toggle

- Widen AdminCandidateEditorModal to size lg for better readability
- Rename "Clip-Compilation" section to "Clip / Compilation", update copy to reflect single clips too, drop upload hint and Clip-Plattform field, rename label to "Link"
- Fix NativeSelect dropdown clipping inside overflow-y-auto modals by teleporting the menu to body with fixed positioning, flip-up logic, and dynamic maxHeight capped to viewport
- Add ClipAdminMenuVisible setting (backend domain, contracts, endpoint, migration) with matching frontend types, defaults, form wiring, and toggle in the Clip-Workflow modal — hides the Clips nav item from the admin sidebar when disabled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
AzuTear
2026-06-27 18:39:35 +02:00
parent 494eba5edd
commit 18b61bed52
119 changed files with 15638 additions and 367 deletions
+41
View File
@@ -2,15 +2,21 @@ import type {
AdminAuditEntriesResponse,
AdminAuditQueryOptions,
AdminDashboardResponse,
AdminOptionalFeatureSettingsResponse,
AdminOperationalSettingsResponse,
AdminNominationLinkBlacklistResponse,
AdminRiskFlagsResponse,
AdminRiskQueryOptions,
AdminRiskRulesResponse,
AdminSeasonDetailResponse,
AdminSeasonListItem,
AdminShowactApplicationItem,
AdminSiteSettingsResponse,
AdminSponsorItem,
AdminTeamResponse,
AdminWorkflowRulesResponse,
ApproveNominationPayload,
AddNominationLinkBlacklistEntryPayload,
BulkResolveRiskFlagsPayload,
CreateTeamMemberPayload,
CreateSeasonPayload,
@@ -19,14 +25,19 @@ import type {
SetAwardResultPayload,
TeamMemberPasswordResponse,
UpdateClipStatusPayload,
UpdateOptionalFeatureSettingsPayload,
UpdateOperationalSettingsPayload,
UpdateRiskRulesPayload,
UpdateShowactStatusPayload,
UpdateNominationLinkBlacklistPayload,
UpdateSeasonPayload,
UpdateSiteSettingsPayload,
UpdateTeamMemberPayload,
UpdateTeamRolesPayload,
UpdateWorkflowRulesPayload,
UpsertCandidatePayload,
UpsertCategoryPayload,
UpsertSponsorPayload,
} from '../../types/awards'
import { requestJson } from '../http'
import { jsonRequest } from './requestOptions'
@@ -82,10 +93,34 @@ export const adminApi = {
getAdminRiskRules: () => requestJson<AdminRiskRulesResponse>('/api/admin/risk-rules'),
updateAdminRiskRules: (payload: UpdateRiskRulesPayload) =>
requestJson<AdminRiskRulesResponse>('/api/admin/risk-rules', jsonRequest('PUT', payload)),
getAdminWorkflowRules: () => requestJson<AdminWorkflowRulesResponse>('/api/admin/workflow-rules'),
updateAdminWorkflowRules: (payload: UpdateWorkflowRulesPayload) =>
requestJson<AdminWorkflowRulesResponse>('/api/admin/workflow-rules', jsonRequest('PUT', payload)),
getAdminSeasons: () => requestJson<AdminSeasonListItem[]>('/api/admin/seasons'),
getAdminSeasonDetail: (seasonId: number) =>
requestJson<AdminSeasonDetailResponse>(`/api/admin/seasons/${seasonId}`),
getAdminShowactApplications: (seasonId: number) =>
requestJson<AdminShowactApplicationItem[]>(`/api/admin/seasons/${seasonId}/showacts`),
updateAdminShowactStatus: (applicationId: number, payload: UpdateShowactStatusPayload) =>
requestJson<{ saved: boolean; application: AdminShowactApplicationItem }>(
`/api/admin/showacts/${applicationId}/status`,
jsonRequest('POST', payload),
),
deleteAdminShowactApplication: (applicationId: number) =>
requestJson<{ deleted: boolean; applicationId: number }>(`/api/admin/showacts/${applicationId}`, { method: 'DELETE' }),
getAdminSponsors: (seasonId: number) =>
requestJson<AdminSponsorItem[]>(`/api/admin/seasons/${seasonId}/sponsors`),
createAdminSponsor: (seasonId: number, payload: UpsertSponsorPayload) =>
requestJson<{ saved: boolean; sponsor: AdminSponsorItem }>(`/api/admin/seasons/${seasonId}/sponsors`, jsonRequest('POST', payload)),
updateAdminSponsor: (sponsorId: number, payload: UpsertSponsorPayload) =>
requestJson<{ saved: boolean; sponsor: AdminSponsorItem }>(`/api/admin/sponsors/${sponsorId}`, jsonRequest('PUT', payload)),
deleteAdminSponsor: (sponsorId: number) =>
requestJson<{ deleted: boolean; sponsorId: number }>(`/api/admin/sponsors/${sponsorId}`, { method: 'DELETE' }),
getAdminSiteSettings: () => requestJson<AdminSiteSettingsResponse>('/api/admin/site-settings'),
getAdminOptionalFeatureSettings: () =>
requestJson<AdminOptionalFeatureSettingsResponse>('/api/admin/optional-feature-settings'),
updateAdminOptionalFeatureSettings: (payload: UpdateOptionalFeatureSettingsPayload) =>
requestJson<AdminOptionalFeatureSettingsResponse>('/api/admin/optional-feature-settings', jsonRequest('PUT', payload)),
getAdminOperationalSettings: () =>
requestJson<AdminOperationalSettingsResponse>('/api/admin/operational-settings'),
getAdminTeam: () => requestJson<AdminTeamResponse>('/api/admin/team'),
@@ -155,6 +190,12 @@ export const adminApi = {
`/api/admin/nominations/${nominationId}/reject`,
jsonRequest('POST', payload),
),
getAdminNominationLinkBlacklist: () =>
requestJson<AdminNominationLinkBlacklistResponse>('/api/admin/nominations/link-blacklist'),
updateAdminNominationLinkBlacklist: (payload: UpdateNominationLinkBlacklistPayload) =>
requestJson<AdminNominationLinkBlacklistResponse>('/api/admin/nominations/link-blacklist', jsonRequest('PUT', payload)),
addAdminNominationLinkBlacklistEntry: (payload: AddNominationLinkBlacklistEntryPayload) =>
requestJson<AdminNominationLinkBlacklistResponse>('/api/admin/nominations/link-blacklist', jsonRequest('POST', payload)),
resolveRiskFlag: (riskFlagId: number, payload: ResolveRiskFlagPayload) =>
requestJson<{ saved: boolean; riskFlagId: number; status: string }>(
`/api/admin/risk-flags/${riskFlagId}/resolve`,