diff --git a/good_asset_type.txt b/good_asset_type.txt new file mode 100644 index 0000000..7ba1d21 --- /dev/null +++ b/good_asset_type.txt @@ -0,0 +1,384 @@ +import { useEffect, useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { useFormik } from "formik"; +import { ArrowLeft, Image as ImageIcon, Video, FileText, Award, Megaphone, HelpCircle, X, Plus, AlertCircle, Settings2, Eye } from "lucide-react"; +import { useAssetType } from "../hook/useAssetType"; +import { assetTypeSchema } from "../validation/asset-types.schema"; +import type { AssetTypeCreateRequest } from "../types/asset-types.types"; + +const CATEGORIES = [ + { id: 'image', label: 'Image', icon: ImageIcon, desc: 'jpg, jpeg, png...' }, + { id: 'video', label: 'Video', icon: Video, desc: 'mp4, mov, avi...' }, + { id: 'document', label: 'Document', icon: FileText, desc: 'pdf, docx, doc...' }, + { id: 'certificate', label: 'Certificate', icon: Award, desc: 'pdf, jpg, png' }, + { id: 'marketing', label: 'Marketing', icon: Megaphone, desc: 'jpg, png, svg...' }, + { id: 'other', label: 'Other', icon: HelpCircle, desc: 'pdf, zip, csv...' }, +] as const; + +export default function NewAssetType() { + const navigate = useNavigate(); + const { id } = useParams<{ id?: string }>(); + const isEdit = Boolean(id); + + const { createItem, updateItem, items, fetchItems } = useAssetType(); + const [newFileType, setNewFileType] = useState(''); + + useEffect(() => { + fetchItems(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const formik = useFormik({ + initialValues: { + name: "", + code: "", + description: "", + status: "active" as "active" | "inactive", + isRequired: false, + category: "" as typeof CATEGORIES[number]['id'] | "", + validation: { + allowedFileTypes: [] as string[], + maxFileSize: 10, + minUploadCount: 0, + maxUploadCount: 1, + } + }, + validationSchema: assetTypeSchema, + onSubmit: async (values, { setSubmitting }) => { + try { + if (isEdit && id) { + await updateItem(id, values as any); + } else { + await createItem(values as AssetTypeCreateRequest); + } + navigate(".."); + } catch { + // Error handled in hook + } finally { + setSubmitting(false); + } + }, + }); + + useEffect(() => { + if (isEdit && id && items.length > 0) { + const match = items.find((item) => item.id === id); + if (match) { + formik.setValues({ + name: match.name, + code: match.code || '', + description: match.description || '', + status: match.status as "active" | "inactive", + isRequired: match.isRequired || false, + category: match.category || '', + validation: match.validation || { + allowedFileTypes: [], + maxFileSize: 10, + minUploadCount: 0, + maxUploadCount: 1, + } + }); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isEdit, id, items]); + + const handleNameChange = (e: React.ChangeEvent) => { + formik.handleChange(e); + if (!isEdit && !formik.touched.code) { + const generatedCode = e.target.value.toLowerCase().replace(/[^a-z0-9]/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, ''); + formik.setFieldValue('code', generatedCode); + } + }; + + const handleAddFileType = () => { + if (newFileType.trim() && !formik.values.validation.allowedFileTypes.includes(newFileType.trim().toLowerCase())) { + formik.setFieldValue('validation.allowedFileTypes', [...formik.values.validation.allowedFileTypes, newFileType.trim().toLowerCase()]); + setNewFileType(''); + } + }; + + const removeFileType = (type: string) => { + formik.setFieldValue('validation.allowedFileTypes', formik.values.validation.allowedFileTypes.filter(t => t !== type)); + }; + + const SectionBadge = ({ num, title, subtitle }: { num: number, title: string, subtitle?: string }) => ( +
+
+ {num} +
+

+ {title} + {subtitle && {subtitle}} +

+
+ ); + + return ( +
+ {/* Top Header */} +
+
+ +
+ Asset Types + + {isEdit ? 'Edit Asset Type' : 'Create Asset Type'} +
+
+
+ + +
+
+ + {/* Main Content Area - Left Aligned */} +
+
+
+ + {/* SECTION 1: Basic Information */} +
+ + +
+
+ + + {formik.touched.name && formik.errors.name &&

{formik.errors.name}

} +
+
+ + +

Unique identifier — auto-generated from name

+
+
+ +
+ +