export type ReportStatus = 'OPEN' | 'UNDER_REVIEW' | 'ASSIGNED' | 'IN_PROGRESS' | 'RESOLVED' | 'REJECTED' | 'CLOSED'; export type MediaKind = 'IMAGE' | 'VIDEO'; export type FlagStatus = 'OPEN' | 'RESOLVED' | 'DISMISSED'; export type FlagContentType = 'REPORT' | 'MESSAGE'; export interface GeoJsonObject { type: string; coordinates: any[]; [key: string]: any; } export interface ErrorResponse { error: string; message?: string; fields?: string[]; } export interface OkResponse { ok: boolean; } /** * USER & AUTHENTICATION */ export interface CurrentUser { id: number; first_name: string; last_name: string; email: string; fiscal_code: string; points: number; must_change_password: boolean; role: string; roles: string[]; permissions: string[]; phone?: string; } export interface AdminUser { id: number; email: string; first_name: string; last_name: string; fiscal_code: string; phone?: string; banned?: boolean; points?: number; must_change_password?: boolean; roles?: string; // Comma-separated } export interface TokenResponse { ok: boolean; token: string; token_type: string; expires_in_hours: number; } /** * REPORTS & MEDIA */ export interface Report { id: number; category_id: number; latitude: number; longitude: number; address: string; description: string; status: ReportStatus; area_id?: number; area_name?: string; category_name?: string; assigned_operator_id?: number; created_at?: string; updated_at?: string; user_id?: number; } export interface OpenDataReport { id: number; category_id: number; category_name: string; latitude: number; longitude: number; status: ReportStatus; created_at: string; updated_at: string; area_id?: number | null; area_name?: string | null; } export interface Media { id: number; report_id: number; url: string; media_kind: MediaKind; content_type: string; original_filename: string; size_bytes: number; created_at: string; } export interface StatusHistoryItem { id: number; report_id: number; changed_by_user_id: number; old_status: ReportStatus; new_status: ReportStatus; note?: string; created_at: string; } export interface Message { id: number; report_id: number; user_id: number; first_name: string; last_name: string; body: string; created_at: string; } /** * ENTITIES (Areas, Teams, Categories, Notifications, Rewards, Moderation) */ export interface Area { id: number; name: string; description?: string; active?: boolean; boundary_geojson?: GeoJsonObject; } export interface Category { id: number; name: string; description?: string; active?: boolean; } export interface Team { id: number; name: string; description?: string; team_category_id: number; area_id?: number; active?: boolean; area_name?: string; category_name?: string; } export interface Notification { id: number; title: string; body: string; type: string; created_at: string; report_id?: number | null; read_at?: string | null; } export interface RewardEvent { id: number; report_id: number; points: number; reason: string; created_at: string; } export interface ModerationFlag { id: number; report_id: number; message_id?: number | null; reason: string; details?: string; status: FlagStatus; content_type: FlagContentType; created_by_user_id: number; created_by_email: string; created_at: string; resolved_by_user_id?: number | null; resolved_by_email?: string | null; resolution_note?: string | null; resolved_at?: string | null; } /** * REQUEST BODIES */ export interface RegisterCitizenRequest { first_name: string; last_name: string; email: string; password: string; fiscal_code: string; phone?: string; birth_date?: string; birth_place?: string; } export interface PasswordLoginRequest { email: string; password: string; } export interface ChangePasswordRequest { current_password: string; new_password: string; } export interface UpdateProfileRequest { first_name?: string; last_name?: string; phone?: string; } export interface EmailRequest { email: string; } export interface VerifyOtpRequest { email: string; code: string; } export interface CreateReportRequest { category_id: number; latitude: number; longitude: number; address: string; description: string; media?: string[]; // Array of URLs if already uploaded } export interface UpdateStatusRequest { status: ReportStatus; note?: string; } export interface AssignTeamRequest { team_id: number; } export interface MessageRequest { body: string; } export interface FeedbackRequest { rating: number; // 1 to 5 comment?: string; } export interface FlagRequest { reason: string; details?: string; } export interface UpdateModerationRequest { status: 'RESOLVED' | 'DISMISSED'; reject_report?: boolean; resolution_note?: string; } export interface CreateAreaRequest { name: string; boundary_geojson: GeoJsonObject; description?: string; } export interface UpdateAreaRequest { name?: string; boundary_geojson?: GeoJsonObject; description?: string; active?: boolean; } export interface CreateCategoryRequest { name: string; description?: string; } export interface UpdateCategoryRequest { name?: string; description?: string; active?: boolean; } export interface CreateTeamRequest { team_category_id: number; name: string; description?: string; area_id?: number; } export interface UpdateTeamRequest { team_category_id?: number; name?: string; description?: string; area_id?: number | null; active?: boolean; } export interface UpdateUserBanRequest { banned: boolean; } export interface UpdateUserRolesRequest { roles: string[]; } /** * RESPONSE BODIES */ export interface CurrentUserResponse { ok: boolean; user: CurrentUser; } export interface RegisterCitizenResponse { ok: boolean; user_id: number; } export interface OtpRequestResponse { ok: boolean; delivery: string; expires_in_minutes: number; } export interface CreateReportResponse { ok: boolean; report_id: number; area_id?: number; } export interface ReportListResponse { ok: boolean; reports: Report[]; } export interface PagedReportListResponse { ok: boolean; page: number; per_page: number; total?: number; reports: Report[]; } export interface OpenDataReportListResponse { ok: boolean; page: number; per_page: number; reports: OpenDataReport[]; } export interface ReportDetailResponse { ok: boolean; report: Report; history: StatusHistoryItem[]; media: Media[]; } export interface InterventionSummaryResponse { ok: boolean; summary: Report; media: Media[]; latest_messages: Message[]; } export interface MediaUploadResponse { ok: boolean; media: Media[]; } export interface MessageListResponse { ok: boolean; messages: Message[]; } export interface FlagResponse { ok: boolean; flag_id: number; } export interface RewardsResponse { ok: boolean; points: number; page: number; per_page: number; reward_events: RewardEvent[]; } export interface NotificationListResponse { ok: boolean; page: number; per_page: number; notifications: Notification[]; } export interface AreaListResponse { ok: boolean; areas: Area[]; } export interface CategoryListResponse { ok: boolean; categories: Category[]; } export interface TeamListResponse { ok: boolean; teams: Team[]; } export interface UserListResponse { ok: boolean; users: AdminUser[]; } export interface ModerationListResponse { ok: boolean; page: number; per_page: number; total?: number; flags: ModerationFlag[]; } export interface OverviewStatsResponse { ok: boolean; reports_by_status: { status: ReportStatus; total: number }[]; reports_by_area: { area: string; total: number }[]; avg_resolution_hours: { value: number }[]; reports_by_category: { category: string; total: number }[]; reports_by_team: { team: string; total: number }[]; monthly_reports: { month: string; total: number }[]; avg_resolution_hours_by_category: { category: string; value: number }[]; avg_resolution_hours_by_area: { area: string; value: number }[]; total_users?: number; open_reports?: number; }