From 878211bc7fe1a9788872f595688d20883e36a480 Mon Sep 17 00:00:00 2001 From: Abizrh Date: Thu, 14 Aug 2025 16:33:19 +0700 Subject: [PATCH] =?UTF-8?q?=E2=9A=A0=EF=B8=8F=20refactor=20(form):=20refac?= =?UTF-8?q?tor=20label=20component=20for=20improved=20styling=20and=20resp?= =?UTF-8?q?onsiveness?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++---- app/components/app/patient/entry-form.vue | 42 +++++++---- app/components/app/patient/list-cfg.ts | 10 +-- app/components/app/patient/list.vue | 2 +- app/components/pub/form/field-group.vue | 70 ++++-------------- app/components/pub/form/label.vue | 74 +++++++------------ app/components/pub/nav/types.ts | 5 +- .../pub/ui/accordion/AccordionContent.vue | 2 +- .../pub/ui/accordion/AccordionItem.vue | 2 +- .../pub/ui/accordion/AccordionTrigger.vue | 2 +- .../pub/ui/alert-dialog/AlertDialogAction.vue | 2 +- .../pub/ui/alert-dialog/AlertDialogCancel.vue | 2 +- .../ui/alert-dialog/AlertDialogContent.vue | 2 +- .../alert-dialog/AlertDialogDescription.vue | 2 +- .../pub/ui/alert-dialog/AlertDialogTitle.vue | 2 +- app/components/pub/ui/avatar/Avatar.vue | 2 +- .../pub/ui/breadcrumb/BreadcrumbEllipsis.vue | 2 +- .../pub/ui/breadcrumb/BreadcrumbLink.vue | 2 +- .../pub/ui/breadcrumb/BreadcrumbSeparator.vue | 2 +- app/components/pub/ui/button/index.ts | 32 ++++---- app/components/pub/ui/calendar/Calendar.vue | 2 +- .../pub/ui/calendar/CalendarCell.vue | 2 +- .../pub/ui/calendar/CalendarCellTrigger.vue | 2 +- .../pub/ui/calendar/CalendarGrid.vue | 2 +- .../pub/ui/calendar/CalendarGridRow.vue | 2 +- .../pub/ui/calendar/CalendarHeadCell.vue | 2 +- .../pub/ui/calendar/CalendarHeader.vue | 2 +- .../pub/ui/calendar/CalendarHeading.vue | 2 +- .../pub/ui/calendar/CalendarNextButton.vue | 2 +- .../pub/ui/calendar/CalendarPrevButton.vue | 2 +- .../pub/ui/carousel/CarouselNext.vue | 2 +- .../pub/ui/carousel/CarouselPrevious.vue | 2 +- app/components/pub/ui/carousel/useCarousel.ts | 4 +- .../pub/ui/chart-area/AreaChart.vue | 2 +- app/components/pub/ui/chart-bar/BarChart.vue | 2 +- .../pub/ui/chart-donut/DonutChart.vue | 2 +- .../pub/ui/chart-line/LineChart.vue | 2 +- app/components/pub/ui/checkbox/Checkbox.vue | 2 +- app/components/pub/ui/command/Command.vue | 2 +- .../pub/ui/command/CommandEmpty.vue | 2 +- .../pub/ui/command/CommandGroup.vue | 2 +- .../pub/ui/command/CommandInput.vue | 2 +- app/components/pub/ui/command/CommandItem.vue | 2 +- app/components/pub/ui/command/CommandList.vue | 2 +- .../pub/ui/command/CommandSeparator.vue | 2 +- .../context-menu/ContextMenuCheckboxItem.vue | 2 +- .../ui/context-menu/ContextMenuContent.vue | 2 +- .../pub/ui/context-menu/ContextMenuItem.vue | 2 +- .../pub/ui/context-menu/ContextMenuLabel.vue | 2 +- .../ui/context-menu/ContextMenuRadioItem.vue | 2 +- .../ui/context-menu/ContextMenuSeparator.vue | 2 +- .../ui/context-menu/ContextMenuSubContent.vue | 2 +- .../ui/context-menu/ContextMenuSubTrigger.vue | 2 +- .../pub/ui/dialog/DialogContent.vue | 2 +- .../pub/ui/dialog/DialogDescription.vue | 2 +- .../pub/ui/dialog/DialogScrollContent.vue | 2 +- app/components/pub/ui/dialog/DialogTitle.vue | 2 +- .../pub/ui/drawer/DrawerContent.vue | 2 +- .../pub/ui/drawer/DrawerDescription.vue | 2 +- .../pub/ui/drawer/DrawerOverlay.vue | 2 +- app/components/pub/ui/drawer/DrawerTitle.vue | 2 +- .../DropdownMenuCheckboxItem.vue | 2 +- .../ui/dropdown-menu/DropdownMenuContent.vue | 2 +- .../pub/ui/dropdown-menu/DropdownMenuItem.vue | 2 +- .../ui/dropdown-menu/DropdownMenuLabel.vue | 2 +- .../dropdown-menu/DropdownMenuRadioItem.vue | 2 +- .../dropdown-menu/DropdownMenuSeparator.vue | 2 +- .../dropdown-menu/DropdownMenuSubContent.vue | 2 +- .../dropdown-menu/DropdownMenuSubTrigger.vue | 2 +- app/components/pub/ui/form/FormItem.vue | 2 +- app/components/pub/ui/form/FormLabel.vue | 10 +-- app/components/pub/ui/form/useFormField.ts | 2 +- .../pub/ui/hover-card/HoverCardContent.vue | 2 +- app/components/pub/ui/label/Label.vue | 2 +- app/components/pub/ui/menubar/Menubar.vue | 2 +- .../pub/ui/menubar/MenubarCheckboxItem.vue | 2 +- .../pub/ui/menubar/MenubarContent.vue | 2 +- app/components/pub/ui/menubar/MenubarItem.vue | 2 +- .../pub/ui/menubar/MenubarLabel.vue | 2 +- .../pub/ui/menubar/MenubarRadioItem.vue | 2 +- .../pub/ui/menubar/MenubarSeparator.vue | 2 +- .../pub/ui/menubar/MenubarSubContent.vue | 2 +- .../pub/ui/menubar/MenubarSubTrigger.vue | 2 +- .../pub/ui/menubar/MenubarTrigger.vue | 2 +- .../pub/ui/navigation-menu/NavigationMenu.vue | 2 +- .../navigation-menu/NavigationMenuContent.vue | 2 +- .../NavigationMenuIndicator.vue | 2 +- .../ui/navigation-menu/NavigationMenuList.vue | 2 +- .../navigation-menu/NavigationMenuTrigger.vue | 2 +- .../NavigationMenuViewport.vue | 2 +- .../pub/ui/number-field/NumberField.vue | 2 +- .../ui/number-field/NumberFieldDecrement.vue | 2 +- .../ui/number-field/NumberFieldIncrement.vue | 2 +- .../pub/ui/number-field/NumberFieldInput.vue | 2 +- .../pub/ui/pagination/PaginationEllipsis.vue | 2 +- .../pub/ui/pagination/PaginationFirst.vue | 8 +- .../pub/ui/pagination/PaginationLast.vue | 8 +- .../pub/ui/pagination/PaginationNext.vue | 8 +- .../pub/ui/pagination/PaginationPrev.vue | 8 +- app/components/pub/ui/pin-input/PinInput.vue | 2 +- .../pub/ui/pin-input/PinInputGroup.vue | 2 +- .../pub/ui/pin-input/PinInputInput.vue | 2 +- .../pub/ui/popover/PopoverContent.vue | 2 +- app/components/pub/ui/progress/Progress.vue | 2 +- .../pub/ui/radio-group/RadioGroup.vue | 2 +- .../pub/ui/radio-group/RadioGroupItem.vue | 2 +- .../pub/ui/range-calendar/RangeCalendar.vue | 2 +- .../ui/range-calendar/RangeCalendarCell.vue | 2 +- .../RangeCalendarCellTrigger.vue | 2 +- .../ui/range-calendar/RangeCalendarGrid.vue | 2 +- .../range-calendar/RangeCalendarGridRow.vue | 2 +- .../range-calendar/RangeCalendarHeadCell.vue | 2 +- .../ui/range-calendar/RangeCalendarHeader.vue | 2 +- .../range-calendar/RangeCalendarHeading.vue | 2 +- .../RangeCalendarNextButton.vue | 2 +- .../RangeCalendarPrevButton.vue | 2 +- .../pub/ui/resizable/ResizableHandle.vue | 2 +- .../pub/ui/resizable/ResizablePanelGroup.vue | 2 +- .../pub/ui/scroll-area/ScrollArea.vue | 2 +- .../pub/ui/scroll-area/ScrollBar.vue | 2 +- .../pub/ui/select/SelectContent.vue | 2 +- app/components/pub/ui/select/SelectGroup.vue | 2 +- app/components/pub/ui/select/SelectItem.vue | 2 +- app/components/pub/ui/select/SelectLabel.vue | 2 +- .../pub/ui/select/SelectScrollDownButton.vue | 2 +- .../pub/ui/select/SelectScrollUpButton.vue | 2 +- .../pub/ui/select/SelectSeparator.vue | 2 +- .../pub/ui/select/SelectTrigger.vue | 2 +- app/components/pub/ui/separator/Separator.vue | 2 +- app/components/pub/ui/sheet/SheetContent.vue | 2 +- .../pub/ui/sheet/SheetDescription.vue | 2 +- app/components/pub/ui/sheet/SheetTitle.vue | 2 +- app/components/pub/ui/sidebar/Sidebar.vue | 6 +- .../pub/ui/sidebar/SidebarGroupAction.vue | 2 +- .../pub/ui/sidebar/SidebarGroupLabel.vue | 2 +- .../pub/ui/sidebar/SidebarMenuAction.vue | 2 +- .../pub/ui/sidebar/SidebarMenuButton.vue | 4 +- .../pub/ui/sidebar/SidebarMenuButtonChild.vue | 2 +- .../pub/ui/sidebar/SidebarMenuSubButton.vue | 2 +- .../pub/ui/sidebar/SidebarProvider.vue | 5 +- app/components/pub/ui/slider/Slider.vue | 2 +- app/components/pub/ui/stepper/Stepper.vue | 2 +- .../pub/ui/stepper/StepperDescription.vue | 2 +- .../pub/ui/stepper/StepperIndicator.vue | 2 +- app/components/pub/ui/stepper/StepperItem.vue | 2 +- .../pub/ui/stepper/StepperSeparator.vue | 2 +- .../pub/ui/stepper/StepperTitle.vue | 2 +- .../pub/ui/stepper/StepperTrigger.vue | 2 +- app/components/pub/ui/switch/Switch.vue | 2 +- app/components/pub/ui/table/TableEmpty.vue | 2 +- .../pub/ui/table/separator/Separator.vue | 2 +- app/components/pub/ui/tabs/TabsContent.vue | 2 +- app/components/pub/ui/tabs/TabsList.vue | 2 +- app/components/pub/ui/tabs/TabsTrigger.vue | 2 +- .../pub/ui/tags-input/TagsInput.vue | 2 +- .../pub/ui/tags-input/TagsInputInput.vue | 2 +- .../pub/ui/tags-input/TagsInputItem.vue | 4 +- .../pub/ui/tags-input/TagsInputItemDelete.vue | 2 +- .../pub/ui/tags-input/TagsInputItemText.vue | 2 +- app/components/pub/ui/textarea/Textarea.vue | 2 +- app/components/pub/ui/toast/Toast.vue | 2 +- app/components/pub/ui/toast/ToastAction.vue | 2 +- app/components/pub/ui/toast/ToastClose.vue | 4 +- .../pub/ui/toast/ToastDescription.vue | 2 +- app/components/pub/ui/toast/ToastTitle.vue | 2 +- app/components/pub/ui/toast/ToastViewport.vue | 2 +- app/components/pub/ui/toast/use-toast.ts | 20 ++--- .../pub/ui/toggle-group/ToggleGroup.vue | 16 ++-- .../pub/ui/toggle-group/ToggleGroupItem.vue | 30 +++++--- app/components/pub/ui/toggle/Toggle.vue | 2 +- .../pub/ui/tooltip/TooltipContent.vue | 2 +- app/pages/(features)/patient/add.vue | 4 +- app/pages/(features)/patient/index.vue | 4 +- 173 files changed, 324 insertions(+), 381 deletions(-) diff --git a/README.md b/README.md index 054f28c5..9dc0e298 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ RSSA - Front End - > [!IMPORTANT] > Read this following instructions before doing your job @@ -65,22 +64,22 @@ The basic development workflow follows these steps: ## Code Conventions - Under the script setup block, putting things in group with the following order: - - Imports → all dependencies, sorted by external, alias (~), and relative imports. - - Props & Emits → clearly define component inputs & outputs. - - State & Computed → all ref, reactive, and computed variables grouped together. - - Lifecycle Hooks → grouped by mounting → updating → unmounting order. - - Functions → async first (fetching, API calls), then utility & event handlers. - - Watchers → if needed, put them at the bottom. - - Template → keep clean and minimal logic, use methods/computed instead of inline JS. + - Imports → all dependencies, sorted by external, alias (~), and relative imports. + - Props & Emits → clearly define component inputs & outputs. + - State & Computed → all ref, reactive, and computed variables grouped together. + - Lifecycle Hooks → grouped by mounting → updating → unmounting order. + - Functions → async first (fetching, API calls), then utility & event handlers. + - Watchers → if needed, put them at the bottom. + - Template → keep clean and minimal logic, use methods/computed instead of inline JS. - Declaration Naming - - Uses PascalCase for `type` naming - - Uses camelCase for `variable` and `const` naming - - Underscore can be used to indicates that a variable has derived from an attribute of an object
- for example: `person_name` indicates it is an attribute `name` from object `person` + - Uses PascalCase for `type` naming + - Uses camelCase for `variable` and `const` naming + - Underscore can be used to indicates that a variable has derived from an attribute of an object
+ for example: `person_name` indicates it is an attribute `name` from object `person` - Looping - - Uses `i`, `j`, `k` as variable for `for` looping index - - Uses `item` as object instantition for `forEach` loop callback - - Uses `item` as object instantition for `v-for` loop callback in the template + - Uses `i`, `j`, `k` as variable for `for` looping index + - Uses `item` as object instantition for `forEach` loop callback + - Uses `item` as object instantition for `v-for` loop callback in the template ## Git Workflows diff --git a/app/components/app/patient/entry-form.vue b/app/components/app/patient/entry-form.vue index 0b636bcf..5768c6a0 100644 --- a/app/components/app/patient/entry-form.vue +++ b/app/components/app/patient/entry-form.vue @@ -13,22 +13,32 @@ import Label from '~/components/pub/form/label.vue'
-
- - - - - - - - - - - - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/app/components/app/patient/list-cfg.ts b/app/components/app/patient/list-cfg.ts index c1131bec..0e1fe7f4 100644 --- a/app/components/app/patient/list-cfg.ts +++ b/app/components/app/patient/list-cfg.ts @@ -1,11 +1,5 @@ -import type { - Col, - KeyLabel, - RecComponent, - RecStrFuncComponent, - RecStrFuncUnknown, - Th, -} from '~/components/pub/nav/types' +import type { Col, KeyLabel, RecComponent, RecStrFuncComponent, RecStrFuncUnknown, Th } from '../../pub/nav/types' +import { defineAsyncComponent } from 'vue' type SmallDetailDto = any diff --git a/app/components/app/patient/list.vue b/app/components/app/patient/list.vue index beba372c..5b8778d9 100644 --- a/app/components/app/patient/list.vue +++ b/app/components/app/patient/list.vue @@ -1,5 +1,5 @@ - + diff --git a/app/components/pub/form/label.vue b/app/components/pub/form/label.vue index b1ad2d55..179cee89 100644 --- a/app/components/pub/form/label.vue +++ b/app/components/pub/form/label.vue @@ -4,69 +4,49 @@ const props = withDefaults( size?: 'default' | 'narrow' | 'wide' height?: 'default' | 'compact' position?: 'default' | 'dynamic' - class?: string }>(), { size: 'default', height: 'default', position: 'default', - class: '', }, ) -const classVal = computed(() => { - let val = '' +const sizeMap = { + default: 'w-28 2xl:w-36', + narrow: 'w-24 2xl:w-28', + wide: 'w-44 2xl:w-48', +} as const - if (props.size === 'narrow') val += 'size-narrow ' - else if (props.size === 'wide') val += 'size-wide ' - else val += 'size-default ' +const heightMap = { + default: 'pt-2 2xl:pt-2.5', + compact: 'leading-[14pt]', +} as const - if (props.height === 'compact') val += 'height-compact ' - else val += 'height-default ' +const positionWrapMap = { + default: 'pe-2 text-start', + dynamic: 'md:text-end', +} as const - if (props.position === 'dynamic') val += 'position-dynamic ' - else val += 'position-default ' +const positionChildMap = { + default: '', + dynamic: 'block pe-2.5', +} as const - return (val + (props.class || '')).trim() -}) +const wrapperClass = computed(() => [ + 'block shrink-0', + sizeMap[props.size], + heightMap[props.height], + positionWrapMap[props.position], +]) + +const labelClass = computed(() => positionChildMap[props.position]) - - diff --git a/app/components/pub/nav/types.ts b/app/components/pub/nav/types.ts index aa4d130b..c1dbe8d3 100644 --- a/app/components/pub/nav/types.ts +++ b/app/components/pub/nav/types.ts @@ -1,4 +1,5 @@ -import type { ComponentType } from '@unovis/ts' +// import type { ComponentType } from '@unovis/ts' +import type { Component } from 'vue' export interface ListItemDto { id: number @@ -6,6 +7,8 @@ export interface ListItemDto { code: string } +export type ComponentType = Component + export interface RecComponent { idx?: number rec: object diff --git a/app/components/pub/ui/accordion/AccordionContent.vue b/app/components/pub/ui/accordion/AccordionContent.vue index 585ad9bb..c3b9e2fa 100644 --- a/app/components/pub/ui/accordion/AccordionContent.vue +++ b/app/components/pub/ui/accordion/AccordionContent.vue @@ -1,9 +1,9 @@ diff --git a/app/components/pub/ui/form/useFormField.ts b/app/components/pub/ui/form/useFormField.ts index 2da133b8..b94b79ae 100644 --- a/app/components/pub/ui/form/useFormField.ts +++ b/app/components/pub/ui/form/useFormField.ts @@ -13,7 +13,7 @@ export function useFormField() { } if (!fieldContext) - throw new Error('useFormField should be used within ') + { throw new Error('useFormField should be used within ') } const { name } = fieldContext const id = fieldItemContext diff --git a/app/components/pub/ui/hover-card/HoverCardContent.vue b/app/components/pub/ui/hover-card/HoverCardContent.vue index f35e3809..47b1517a 100644 --- a/app/components/pub/ui/hover-card/HoverCardContent.vue +++ b/app/components/pub/ui/hover-card/HoverCardContent.vue @@ -1,7 +1,6 @@ diff --git a/app/components/pub/ui/menubar/MenubarRadioItem.vue b/app/components/pub/ui/menubar/MenubarRadioItem.vue index a4d72455..688034dc 100644 --- a/app/components/pub/ui/menubar/MenubarRadioItem.vue +++ b/app/components/pub/ui/menubar/MenubarRadioItem.vue @@ -1,7 +1,6 @@