/** * Hand-written types for the gig-platform admin API. * * The scribe-generated `types.gen.ts` covers paths/params, but its response * schemas are example-based and incomplete — the envelope and entities below * are the source of truth for data shapes (mirrors CLAUDE.md API design). */ // ---------- envelope ---------- export interface ApiResponse { success: boolean data: T message?: string meta?: Record } export interface Pagination { current_page: number next_page: number | null page_size: number prev_page: number | null total_count: number total_pages: number } export interface PaginatedResponse extends ApiResponse { pagination: Pagination } export interface ApiErrorPayload { success: false code: string message: string data?: { errors?: Record } & Record } export interface ListParams { page?: number page_size?: number [key: string]: string | number | boolean | undefined } // ---------- auth ---------- export interface TokenGrant { token_type: string expires_in: number access_token: string refresh_token?: string } export interface AdminUser { kind: 'user' uid: string sid?: string | null username: string | null email: string | null phone: string | null display_name: string | null avatar: string | null status: boolean | string is_robot?: boolean } export interface MeResponse extends ApiResponse { meta: { roles: string[] permissions: string[] } } // ---------- category ---------- export interface CategoryTranslation { locale: string name: string description: string | null } export interface Category { kind: 'category' id: string parent_id: string | null level: number slug: string name: string | null description: string | null sort_order: number is_active: boolean visibility?: string approval_status?: 'pending' | 'approved' | 'rejected' | string source?: string created_by_uid?: string | null approved_by_uid?: string | null approved_at?: string | null merged_into_category_id?: string | null translations?: CategoryTranslation[] children?: Category[] created_at?: string updated_at?: string } // ---------- studio ---------- export type ArticleStatus = | 'planned' | 'drafting' | 'drafted' | 'published' | 'scheduled' export interface StudioArticle { kind: 'studio_article' id: string series_id: string robot_author_id: string category_id: string | null subtopic_id: string | null article_number: number plan: Record | null outline: Record | null title: string | null summary: string | null key_takeaways: string[] | null cta: string | null tags: string[] | null seo_keywords: string[] | null cover_image_prompt: string | null cover_asset_id: string | null cover_image: { url: string; alt?: string | null } | null inline_images: Array<{ url: string; alt?: string | null }> | null inline_image_prompts: unknown[] | null status: ArticleStatus publish_schedule: Record | null dimzou_document_id: number | null dimzou_publication_id: number | null created_at: string updated_at: string } export type RobotAuthorStatus = 'pending' | 'profiling' | 'ready' | 'paused' export interface StudioRobotAuthor { kind: 'studio_robot_author' id: string user_uid: string category_id: string subtopic_id: string | null persona: string | null positioning: string | null target_readers: string | null article_style: Record | null image_style: Record | null publishing_rules: Record | null status: RobotAuthorStatus source: 'user' | 'category' created_at: string updated_at: string } export type SeriesStatus = 'planned' | 'in_progress' | 'complete' export interface StudioSeries { kind: 'studio_series' id: string category_id: string subtopic_id: string | null robot_author_id: string goal: string | null reader_journey: string | null target_article_count: number | null planned_articles: unknown[] | null status: SeriesStatus created_at: string updated_at: string } export interface StudioSubtopic { kind: 'studio_subtopic' id: string category_id: string title: string target_audience: string | null pain_points: string | null content_value: string | null expandability_score: number | null status: 'active' | 'archived' created_at: string updated_at: string } export interface StudioCategoryBrief { kind: 'studio_category_brief' id: string category_id: string description: string | null target_audience: string | null content_angles: string[] | null risk_notes: string | null subtopic_count: number author_count: number article_count: number created_at: string updated_at: string } export interface StudioStylePreset { kind: 'studio_style_preset' id: string type: 'article' | 'image' | 'bundle' name: string payload: Record created_at: string updated_at: string } export interface StudioAgentToken { kind: 'studio_agent_token' id: string scopes: string[] | null created_at: string | null expires_at: string | null } export interface StudioAgentTokenGrant extends TokenGrant { kind: 'studio_agent_token_grant' connect: { endpoint: string; header: string } } // ---------- sid / locales / devices ---------- export interface SidRule { id?: number key: string description: string | null enabled: boolean created_at?: string updated_at?: string } export interface LuckyNumber { id: number number: string category: string | null enabled: boolean created_by?: string | null created_at?: string updated_at?: string } export interface SidCheckResult { sid: string reserved: boolean reasons?: string[] } export interface LocaleRow { kind?: string code: string name: string native_name: string is_active: boolean sort_order: number created_at?: string updated_at?: string } export interface NotificationDevice { id: number | string device_id?: string user_uid?: string | null platform?: string model?: string | null is_online?: boolean active_sessions_count?: number last_seen_at?: string | null created_at?: string }