Files
picpeak/frontend/src/services/setup.service.ts
T
Paul Nothaft 7eb6357b4a feat(setup): event-types step in first-run wizard + un-hardcode event type deps (#800)
Fresh installs can now shape the event-type catalog during the setup
wizard — rename, delete or replace the seeded defaults while nothing
references them. On existing installs system types stay protected.

- New wizard step between features and config: edit name/URL prefix,
  remove, or add types; defaults shown as recommendations
- setup_wizard_completed app setting (migration 161): seeded true when
  an admin already exists, false on fresh installs; POST /api/setup/
  complete (adminAuth) flips it when the wizard finishes
- deleteEventType: system types deletable only while the flag is unset;
  in-use check extended to quotes; per-type reminder template
  (event_reminder_<slug>) is deleted with the type
- reminder-template self-heal no longer resurrects templates for slugs
  removed from the catalog
- v1 API event creation validates event_type against the live catalog
  instead of a hardcoded whitelist (custom types were rejected; the
  never-seeded 'family' slug is no longer silently accepted)
- contract→event conversion resolves the event type via
  crm_default_event_type / resolveDefaultEventType instead of
  hardcoding 'wedding' (resolveDefaultEventType moved from quoteService
  to eventTypeService for reuse)
2026-07-15 21:30:23 +02:00

49 lines
1.6 KiB
TypeScript

import { api } from '../config/api';
export interface SetupStatus {
needsAdmin: boolean;
complete: boolean;
}
export interface SetupAdminUser {
id: number;
username: string;
email: string;
role: { name: string; displayName?: string };
}
export interface CreateInitialAdminInput {
token: string;
email: string;
password: string;
}
// First-run bootstrap. Public endpoints that self-close once an admin exists.
export const setupService = {
async getSetupStatus(): Promise<SetupStatus> {
const response = await api.get<SetupStatus>('/setup/status');
return response.data;
},
// Step-1 pre-flight: confirm the token is valid before advancing to the
// account step. Rejects (400, field: 'token') on a wrong token without
// burning it. Throws on non-2xx so the caller can branch on the status.
async verifyToken(token: string): Promise<{ valid: boolean }> {
const response = await api.post<{ valid: boolean }>('/setup/verify-token', { token });
return response.data;
},
async createInitialAdmin(input: CreateInitialAdminInput): Promise<{ user: SetupAdminUser }> {
// Admin JWT is returned as an HttpOnly cookie (mirrors login); body carries the user.
const response = await api.post<{ user: SetupAdminUser }>('/setup/admin', input);
return response.data;
},
// One-way wizard-finish marker (authenticated — runs after the admin
// exists). While unset, the wizard's event-types step may delete the
// seeded system types; afterwards they are permanently protected.
async completeSetup(): Promise<void> {
await api.post('/setup/complete');
},
};