mosaicmap/types/admin-panel.ts
2025-08-14 21:34:16 +08:00

197 lines
4.5 KiB
TypeScript

import { ReactNode } from "react";
export type FieldType =
| "input"
| "textarea"
| "select"
| "switch"
| "slider"
| "checkbox"
| "radio"
| "number"
| "password"
| "email"
| "url"
| "date"
| "time"
| "datetime-local"
| "color"
| "file"
| "range"
| "tel";
export interface SelectOption {
label: string;
value: string | number;
disabled?: boolean;
description?: string;
}
export interface ValidationRule {
required?: boolean;
min?: number;
max?: number;
minLength?: number;
maxLength?: number;
pattern?: RegExp;
custom?: (value: any) => string | null;
}
export interface FieldConfig {
id: string;
label: string;
description?: string;
type: FieldType;
value: any;
placeholder?: string;
disabled?: boolean;
readOnly?: boolean;
validation?: ValidationRule;
// Type-specific props
options?: SelectOption[];
min?: number;
max?: number;
step?: number;
accept?: string; // for file input
multiple?: boolean;
rows?: number; // for textarea
// Layout props
grid?: {
span?: number;
offset?: number;
};
// Conditional rendering
dependsOn?: string;
showWhen?: (values: Record<string, any>) => boolean;
// Custom render function
render?: (field: FieldConfig, value: any, onChange: (value: any) => void) => ReactNode;
}
export interface SectionConfig {
id: string;
title: string;
description?: string;
icon?: ReactNode;
collapsed?: boolean;
fields: FieldConfig[];
// Layout
columns?: number;
// Access control
permissions?: string[];
// Custom render
render?: (section: SectionConfig, children: ReactNode) => ReactNode;
}
export interface TabConfig {
id: string;
title: string;
icon?: ReactNode;
badge?: string | number;
disabled?: boolean;
sections: SectionConfig[];
// Access control
permissions?: string[];
}
export interface ActionConfig {
id: string;
label: string;
icon?: ReactNode;
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
size?: "default" | "sm" | "lg" | "icon";
disabled?: boolean;
loading?: boolean;
permissions?: string[];
onClick: () => void | Promise<void>;
}
export interface HeaderConfig {
title: string;
description?: string;
actions?: ActionConfig[];
breadcrumbs?: Array<{
label: string;
href?: string;
}>;
}
export interface AdminPanelConfig {
header: HeaderConfig;
tabs: TabConfig[];
// Global settings
autoSave?: boolean;
autoSaveDelay?: number;
// Validation
validateOnChange?: boolean;
validateOnSubmit?: boolean;
// Callbacks
onValueChange?: (path: string, value: any, allValues: Record<string, any>) => void;
onSave?: (values: Record<string, any>) => Promise<void>;
onReset?: () => void;
onValidate?: (values: Record<string, any>) => Record<string, string>;
// Theme
theme?: {
spacing?: "compact" | "normal" | "relaxed";
layout?: "sidebar" | "tabs";
};
}
export interface AdminPanelState {
values: Record<string, any>;
errors: Record<string, string>;
dirty: Record<string, boolean>;
loading: boolean;
saving: boolean;
}
// Hook types
export interface UseAdminPanelOptions {
config: AdminPanelConfig;
initialValues?: Record<string, any>;
onSubmit?: (values: Record<string, any>) => Promise<void>;
}
export interface UseAdminPanelReturn {
state: AdminPanelState;
actions: {
setValue: (path: string, value: any) => void;
setValues: (values: Record<string, any>) => void;
resetValue: (path: string) => void;
resetAll: () => void;
save: () => Promise<void>;
validate: () => boolean;
clearErrors: () => void;
};
helpers: {
getValue: (path: string) => any;
getError: (path: string) => string | undefined;
isDirty: (path?: string) => boolean;
isValid: (path?: string) => boolean;
};
}
// Data providers
export interface AdminDataProvider {
load: () => Promise<Record<string, any>>;
save: (values: Record<string, any>) => Promise<void>;
validate?: (values: Record<string, any>) => Promise<Record<string, string>>;
}
// Permission system
export interface PermissionChecker {
hasPermission: (permission: string) => boolean;
hasAnyPermission: (permissions: string[]) => boolean;
hasAllPermissions: (permissions: string[]) => boolean;
}