From f6229b31bf076576a6fe8ae62604ceabf7e33d43 Mon Sep 17 00:00:00 2001 From: ReLoia Date: Sun, 7 Jun 2026 20:01:54 +0200 Subject: [PATCH] feat: add API type definitions and bootstrap-italia configuration - Define comprehensive API request/response types - Add environment configuration template - Add Bootstrap Italia plugin setup - Include SVG sprites for icon system Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .env.example | 2 + app/plugins/bootstrap-italia.client.ts | 3 + app/types/api.d.ts | 409 +++++++++++++++++++++++++ public/sprites.svg | 1 + 4 files changed, 415 insertions(+) create mode 100644 .env.example create mode 100644 app/plugins/bootstrap-italia.client.ts create mode 100644 app/types/api.d.ts create mode 100644 public/sprites.svg diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..17c3a9f --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +# Public URL of the website +NUXT_SITE_URL=http://localhost:3000 diff --git a/app/plugins/bootstrap-italia.client.ts b/app/plugins/bootstrap-italia.client.ts new file mode 100644 index 0000000..0ec5159 --- /dev/null +++ b/app/plugins/bootstrap-italia.client.ts @@ -0,0 +1,3 @@ +export default defineNuxtPlugin(async (nuxtApp) => { + await import('bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js') +}) \ No newline at end of file diff --git a/app/types/api.d.ts b/app/types/api.d.ts new file mode 100644 index 0000000..0812e1c --- /dev/null +++ b/app/types/api.d.ts @@ -0,0 +1,409 @@ +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 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 CreateCategoryRequest { + name: string; + description?: string; +} + +export interface CreateTeamRequest { + team_category_id: number; + name: string; + description?: string; + area_id?: number; +} + +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; + 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; + 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 }[]; +} \ No newline at end of file diff --git a/public/sprites.svg b/public/sprites.svg new file mode 100644 index 0000000..b3c20b2 --- /dev/null +++ b/public/sprites.svg @@ -0,0 +1 @@ + \ No newline at end of file