441 lines
8.6 KiB
TypeScript
441 lines
8.6 KiB
TypeScript
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;
|
|
}
|