From aa7b6581d968bc54bab625b175994764918331b3 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Sat, 11 Oct 2025 02:03:10 +0700 Subject: [PATCH] feat/FE/US-34/TASK-54-51-slicing-ui-client-side-validation-stock-adjustment --- .prettierrc | 15 + src/app/inventory/adjustment/add/page.tsx | 11 + src/app/inventory/adjustment/detail/page.tsx | 11 + src/app/inventory/adjustment/page.tsx | 12 + src/components/input/RadioInput.tsx | 114 ++++++ src/components/input/TextArea.tsx | 124 ++++++ .../adjustment/InventoryAdjustmentTable.tsx | 334 +++++++++++++++ .../form/InventoryAdjustmentForm.schema.ts | 34 ++ .../form/InventoryAdjustmentForm.tsx | 385 ++++++++++++++++++ src/config/constant.ts | 12 + src/services/api/inventory.ts | 11 + src/types/api/inventory/adjustment.d.ts | 31 ++ 12 files changed, 1094 insertions(+) create mode 100644 .prettierrc create mode 100644 src/app/inventory/adjustment/add/page.tsx create mode 100644 src/app/inventory/adjustment/detail/page.tsx create mode 100644 src/app/inventory/adjustment/page.tsx create mode 100644 src/components/input/RadioInput.tsx create mode 100644 src/components/input/TextArea.tsx create mode 100644 src/components/pages/inventory/adjustment/InventoryAdjustmentTable.tsx create mode 100644 src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.schema.ts create mode 100644 src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx create mode 100644 src/services/api/inventory.ts create mode 100644 src/types/api/inventory/adjustment.d.ts diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..250df482 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "singleQuote": true, + "jsxSingleQuote": true, + "endOfLine": "lf", + "arrowParens": "always", + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "printWidth": 80, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "semi": true, + "tabWidth": 2, + "trailingComma": "es5" +} diff --git a/src/app/inventory/adjustment/add/page.tsx b/src/app/inventory/adjustment/add/page.tsx new file mode 100644 index 00000000..3bd64573 --- /dev/null +++ b/src/app/inventory/adjustment/add/page.tsx @@ -0,0 +1,11 @@ +import InventoryAdjustmentForm from "@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm"; + +const CreateInventoryAdjustment = () => { + return ( +
+ +
+ ); +} + +export default CreateInventoryAdjustment; \ No newline at end of file diff --git a/src/app/inventory/adjustment/detail/page.tsx b/src/app/inventory/adjustment/detail/page.tsx new file mode 100644 index 00000000..2325c4a0 --- /dev/null +++ b/src/app/inventory/adjustment/detail/page.tsx @@ -0,0 +1,11 @@ +import InventoryAdjustmentForm from "@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm"; + +const DetailInventoryAdjustment = () => { + return ( +
+ +
+ ); +} + +export default DetailInventoryAdjustment; \ No newline at end of file diff --git a/src/app/inventory/adjustment/page.tsx b/src/app/inventory/adjustment/page.tsx new file mode 100644 index 00000000..95199079 --- /dev/null +++ b/src/app/inventory/adjustment/page.tsx @@ -0,0 +1,12 @@ +import InventoryAdjustmentForm from '@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm'; +import InventoryAdjustmentTable from '@/components/pages/inventory/adjustment/InventoryAdjustmentTable'; + +const InventoryAdjustment = () => { + return ( +
+ +
+ ); +}; + +export default InventoryAdjustment; diff --git a/src/components/input/RadioInput.tsx b/src/components/input/RadioInput.tsx new file mode 100644 index 00000000..de3f23f5 --- /dev/null +++ b/src/components/input/RadioInput.tsx @@ -0,0 +1,114 @@ +'use client'; + +import { ChangeEventHandler, ReactNode } from 'react'; +import { cn } from '@/lib/helper'; + +export interface RadioOption { + label: string; + value: string; +} + +export interface RadioInputProps { + label?: string; + bottomLabel?: string; + name: string; + value?: string; + options: RadioOption[]; + variant?: string; // contoh: 'radio-primary', 'radio-secondary', dll + className?: { + wrapper?: string; + label?: string; + radioWrapper?: string; + radio?: string; + }; + isError?: boolean; + isValid?: boolean; + errorMessage?: string; + required?: boolean; + disabled?: boolean; + startAdornment?: ReactNode; + endAdornment?: ReactNode; + onChange?: ChangeEventHandler; + onBlur?: (e: React.FocusEvent) => void; +} + +const RadioInput = ({ + label, + bottomLabel, + name, + value, + options, + variant = 'radio-primary', + className, + isError, + isValid, + errorMessage, + required = false, + disabled = false, + onChange, + onBlur, +}: RadioInputProps) => { + return ( +
+ {/* Label atas */} + {label && ( + + )} + + {/* Daftar opsi radio */} +
+ {options.map((option) => ( + + ))} +
+ + {/* Label bawah */} + {!isError && bottomLabel && ( +

{bottomLabel}

+ )} + + {/* Pesan error */} + {isError && errorMessage && ( +

{errorMessage}

+ )} +
+ ); +}; + +export default RadioInput; diff --git a/src/components/input/TextArea.tsx b/src/components/input/TextArea.tsx new file mode 100644 index 00000000..b4a6c9f5 --- /dev/null +++ b/src/components/input/TextArea.tsx @@ -0,0 +1,124 @@ +'use client'; + +import { + ChangeEventHandler, + FocusEventHandler, + ReactNode, +} from 'react'; + +import { cn } from '@/lib/helper'; + +export interface TextAreaProps { + label?: string; + bottomLabel?: string; + name: string; + value?: string | number; + placeholder?: string; + className?: { + wrapper?: string; + label?: string; + inputWrapper?: string; + input?: string; + }; + isError?: boolean; + isValid?: boolean; + disabled?: boolean; + readOnly?: boolean; + required?: boolean; + isLoading?: boolean; + errorMessage?: string; + startAdornment?: ReactNode; + endAdornment?: ReactNode; + onChange?: ChangeEventHandler; + onBlur?: FocusEventHandler; + cols?: number; +} + +const TextArea = ({ + label, + bottomLabel, + name, + value, + placeholder, + className, + isError, + isValid, + errorMessage, + startAdornment, + endAdornment, + disabled = false, + required = false, + onChange, + onBlur, + readOnly = false, + isLoading = false, + cols = 3 +}: TextAreaProps) => { + return ( +
+ {label && ( + + )} + {startAdornment && startAdornment} + +