- Add `telecart_forms` table migration and default checkout form seeder - Implement `FormsHandler` to fetch form schemas - Update `OrderCreateService` to handle custom fields in order comments - Add `update` method to QueryBuilder and Grammar - Add `Arr::except` helper - Update composer dependencies (Carbon, Symfony, PHPUnit, etc.) - Improve `MigratorService` error handling - Add unit tests for new functionality
4.5 KiB
4.5 KiB
FormBuilder System Context
Architectural Overview
The FormBuilder ecosystem is a strictly typed Vue 3 application module designed to generate standard FormKit Schema JSON. It eschews internal DTOs in favor of direct schema manipulation.
Core Components
-
FormBuilderView (
views/FormBuilderView.vue):- Role: Smart container / Data fetcher.
- Responsibility: Fetches form data from API (
GET /api/admin/forms/{alias}), handles loading states, and passes data toFormBuilder. - Contract: Expects API response
{ data: { schema: Array, is_custom: Boolean, ... } }.
-
FormBuilder (
components/FormBuilder/FormBuilder.vue):- Role: Main Orchestrator / State Owner.
- Responsibility: Manages
v-model(schema), mode switching (Visual/Code/Preview), and provides state to children. - State Management: Uses
defineModelforformFields(schema) andisCustom(mode flag). Usesprovide('formFields')andprovide('selectedFieldId')for deep dependency injection. - Modes:
- Visual: Drag-and-drop interface using
vuedraggable. - Code: Direct JSON editing of the FormKit schema. Sets
isCustom = true. - Preview: Renders the current schema using
FormKit.
- Visual: Drag-and-drop interface using
-
FormCanvas (
components/FormBuilder/FormCanvas.vue):- Role: Visual Editor Surface.
- Responsibility: Renders the draggable list of fields.
- Implementation: Uses
vuedraggablebound toformFields. - UX: Implements "Ghost" and "Drag" classes for visual feedback. Handles selection logic.
-
FieldsPanel (
components/FormBuilder/FieldsPanel.vue):- Role: Component Palette.
- Responsibility: Source of truth for available field types.
- Implementation: Uses
vuedraggablewithpull: 'clone', put: falseto spawn new fields.
-
FieldSettings (
components/FormBuilder/FieldSettings.vue):- Role: Property Editor.
- Responsibility: Edits properties of the
selectedFieldId. - Constraint: Must use PrimeVue components for all inputs.
Data Flow & Invariants
- Schema Authority: The FormKit Schema JSON is the single source of truth. There is no "internal model" separate from the schema.
- Reactivity:
formFieldsis an Array of Objects.- Mutations must preserve reactivity. When using
v-modelorprovide/inject, ensure array methods (splice, push, filter) are used correctly or replace the entire array reference if needed to trigger watchers. - Immutability:
useFormFieldscomposable uses immutable patterns (returning new array references) to ensuredefineModelin parent detects changes.
- Mode Logic:
- Switching to Code mode sets
isCustom = true. - Switching to Visual mode sets
isCustom = false. - Safety: Switching modes triggers JSON validation. Invalid JSON prevents mode switch.
- Switching to Code mode sets
- Drag and Drop:
- Powered by
vuedraggable(Sortable.js). - Clone Logic:
FieldsPanelclones fromavailableFields.FormCanvasreceives the clone. - ID Generation: Unique IDs are generated upon cloning/addition to ensure key stability.
- Powered by
Naming & Conventions
- Tailwind: Use
tw:prefix for all utility classes (e.g.,tw:flex,tw:p-4). - Components: PrimeVue components are the standard UI kit (Button, Panel, InputText, etc.).
- Icons: FontAwesome (
fa fa-*). - Files: PascalCase for components (
FormBuilder.vue), camelCase for logic (useFormFields.js).
Integration Rules
- Backend: The backend stores the JSON blob directly.
FormBuilderdoes not transform data before save; it emits the raw schema. - API:
useFormsStorehandles API communication.
Pitfalls & Warnings
- vuedraggable vs @formkit/drag-and-drop: We strictly use
vuedraggable. Do not re-introduce@formkit/drag-and-drop. - Watchers: Avoid
watchwherecomputedor event handlers suffice, to prevent infinite loops in bidirectional data flow. - Tailwind Config: Do not use
@applywithtw:prefixed classes in<style>blocks; standard CSS properties should be used if custom classes are needed.
Future Modifications
- Adding Fields: Update
constants/availableFields.jsand ensureutils/fieldHelpers.jssupports the new type. - Validation: FormKit validation rules string (e.g., "required|email") is edited as a raw string in
FieldSettings. Complex validation builders would require a new UI component.