23 lines
1.9 KiB
Markdown
23 lines
1.9 KiB
Markdown
# Plan: Refactor FileUploadSection into generic FileUploadField
|
|
|
|
Replace the composite, internally-coupled `FileUploadSection` with a generic, controlled `FileUploadField` component. Business logic (validation helpers, toast errors, URL generation) moves up into `CreateArticleForm`, and two `FileUploadField` instances replace the single `FileUploadSection`.
|
|
|
|
## Steps
|
|
|
|
1. Create `file-upload-field.tsx` as a controlled `FileUploadField` component accepting `file: File | null`, `onFileChange: (file: File | null) => void`, `accept`, `validate`, `label`, `description`, and `error` props — rendering the `FileUpload`/`Field` UI shell with no internal business logic.
|
|
|
|
2. Move `isImageFile`, `isContentFile`, `generateFakeImageUrl`, and rejection-toast handlers into `create-article-form.tsx`, adding `coverImageFile` and `contentFile` state entries (or keeping them as `useForm` values directly).
|
|
|
|
3. Replace the `<FileUploadSection>` block in `create-article-form.tsx` with two `<FileUploadField>` instances (one for cover image, one for content), wiring each one to the form state via `Controller` or direct `setValue`.
|
|
|
|
4. Delete `file-upload-section.tsx` now that it has no consumers.
|
|
|
|
## Further Considerations
|
|
|
|
1. **`onFileChange` vs `setFile`** — `onFileChange` follows idiomatic React event-prop naming; `setFile` reads more like a state-setter leak. `onFileChange` is recommended but either works.
|
|
|
|
2. **State ownership for files** — Cover image needs a `File` reference for URL revocation cleanup; should this live in a `useState` inside the form or in the `FileUploadField` itself via a ref? Keeping it inside the form is cleaner for reset logic.
|
|
|
|
3. **Null on clear** — The `onFileChange(null)` case (user deletes the file) should also clear the related form field value (`coverImageUrl` → `''`, `content` → `''`), so the handler in the form needs to handle both `File` and `null`.
|
|
|