From ce1d5f90156913e27652261c998fe32bc8e0545b Mon Sep 17 00:00:00 2001 From: bicochan Date: Fri, 28 Feb 2025 16:02:04 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20data=20table=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/components/src/ui/button/index.tsx | 2 +- .../src/ui/data-table/data-table.stories.tsx | 160 ++++++++++-------- .../components/src/ui/data-table/index.tsx | 17 +- 3 files changed, 93 insertions(+), 86 deletions(-) diff --git a/packages/common/components/src/ui/button/index.tsx b/packages/common/components/src/ui/button/index.tsx index 8c3061af7..258a01fa0 100644 --- a/packages/common/components/src/ui/button/index.tsx +++ b/packages/common/components/src/ui/button/index.tsx @@ -24,7 +24,7 @@ const buttonVariants = cva( size: { default: "h-[3.2rem] px-10", xs: "h-8 px-2 !text-[1.1rem]", - sm: "h-10 px-4", + sm: "h-10 px-4 !text-[1.2rem]", lg: "h-16 px-12", icon: "h-10 w-10", }, diff --git a/packages/common/components/src/ui/data-table/data-table.stories.tsx b/packages/common/components/src/ui/data-table/data-table.stories.tsx index 6463bed52..62237cc07 100644 --- a/packages/common/components/src/ui/data-table/data-table.stories.tsx +++ b/packages/common/components/src/ui/data-table/data-table.stories.tsx @@ -1,5 +1,9 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { createColumnHelper } from "@tanstack/react-table"; +import { + createColumnHelper, + getCoreRowModel, + useReactTable, +} from "@tanstack/react-table"; import { DataTable } from "."; const meta: Meta = { @@ -14,8 +18,6 @@ const meta: Meta = { }, source: { code: ` -import { createColumnHelper } from "@tanstack/react-table"; - type Person = { firstName: string; lastName: string; @@ -25,7 +27,7 @@ type Person = { progress: number; }; -const defaultData: Person[] = [ +const data: Person[] = [ { firstName: "tanner", lastName: "linsley", @@ -78,7 +80,17 @@ const columns = [ }), ]; -return ; + +function Table() { + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + }); + + return ; +} + `, }, }, @@ -89,69 +101,77 @@ export default meta; type Story = StoryObj; export const Default: Story = { - render: () => { - type Person = { - firstName: string; - lastName: string; - age: number; - visits: number; - status: string; - progress: number; - }; - - const defaultData: Person[] = [ - { - firstName: "tanner", - lastName: "linsley", - age: 24, - visits: 100, - status: "In Relationship", - progress: 50, - }, - { - firstName: "tandy", - lastName: "miller", - age: 40, - visits: 40, - status: "Single", - progress: 80, - }, - { - firstName: "joe", - lastName: "dirte", - age: 45, - visits: 20, - status: "Complicated", - progress: 10, - }, - ]; - - const columnHelper = createColumnHelper(); - - const columns = [ - columnHelper.accessor("firstName", { - cell: (info) => info.getValue(), - }), - columnHelper.accessor((row) => row.lastName, { - id: "lastName", - cell: (info) => {info.getValue()}, - header: () => Last Name, - }), - columnHelper.accessor("age", { - header: () => "Age", - cell: (info) => info.renderValue(), - }), - columnHelper.accessor("visits", { - header: () => Visits, - }), - columnHelper.accessor("status", { - header: "Status", - }), - columnHelper.accessor("progress", { - header: "Profile Progress", - }), - ]; - - return ; - }, + render: () =>
, }; + +type Person = { + firstName: string; + lastName: string; + age: number; + visits: number; + status: string; + progress: number; +}; + +const data: Person[] = [ + { + firstName: "tanner", + lastName: "linsley", + age: 24, + visits: 100, + status: "In Relationship", + progress: 50, + }, + { + firstName: "tandy", + lastName: "miller", + age: 40, + visits: 40, + status: "Single", + progress: 80, + }, + { + firstName: "joe", + lastName: "dirte", + age: 45, + visits: 20, + status: "Complicated", + progress: 10, + }, +]; + +const columnHelper = createColumnHelper(); + +const columns = [ + columnHelper.accessor("firstName", { + cell: (info) => info.getValue(), + }), + columnHelper.accessor((row) => row.lastName, { + id: "lastName", + cell: (info) => {info.getValue()}, + header: () => Last Name, + }), + columnHelper.accessor("age", { + header: () => "Age", + cell: (info) => info.renderValue(), + }), + columnHelper.accessor("visits", { + header: () => Visits, + }), + columnHelper.accessor("status", { + header: "Status", + }), + columnHelper.accessor("progress", { + header: "Profile Progress", + }), +]; + +function Table() { + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + }); + + return ; +} diff --git a/packages/common/components/src/ui/data-table/index.tsx b/packages/common/components/src/ui/data-table/index.tsx index 0c7cd7e3e..4b0ba901b 100644 --- a/packages/common/components/src/ui/data-table/index.tsx +++ b/packages/common/components/src/ui/data-table/index.tsx @@ -1,8 +1,5 @@ import { flexRender, - getCoreRowModel, - useReactTable, - type ColumnDef, type RowData, type Table as TableType, } from "@tanstack/react-table"; @@ -39,19 +36,9 @@ function THead({ table }: { table: TableType }) { ); } -interface TableProps { - data: T[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - columns: ColumnDef[]; -} - -function DataTable({ data, columns }: TableProps) { - const table = useReactTable({ - data, - columns, - getCoreRowModel: getCoreRowModel(), - }); +type TableProps = { table: TableType }; +function DataTable({ table }: TableProps) { return (
From c4e021f8b59b7c255014397256d1d4cae57b6817 Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Fri, 28 Feb 2025 16:47:19 +0900 Subject: [PATCH 2/4] =?UTF-8?q?chart.md=20=ED=8C=8C=EC=9D=BC=20=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/business_components/chart.md | 87 ++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 packages/common/business_components/chart.md diff --git a/packages/common/business_components/chart.md b/packages/common/business_components/chart.md new file mode 100644 index 000000000..ceacc3a69 --- /dev/null +++ b/packages/common/business_components/chart.md @@ -0,0 +1,87 @@ +## Chart 모듈 +### 공통 모듈 중 Chart를 다양한 테마로 적용시킬 수 있도록 해주는 모듈 +  1. 차트 모듈 사용법 + +    1-1) 설정 + +      (1) tsconfig.json 'path'에 '@common/business_components' 변수를 추가 +```json +"paths": { + "@/*": ["./*"], + "@common/components/*": ["../../packages/common/components/src/*"], + "@common/components": ["../../packages/common/components/src/index"], + // 작성구문문 + "@common/business_components/*": ["../../packages/common/business_components/src/*"], + "@common/business_components": ["../../packages/common/business_components/src/index"] +} +``` +      (2) package.json 'dependencies'에 '@common/business_components' 추가 +```json +"dependencies": { + "@common/business_components": "workspace:*", + "next": "15.1.7" +}, +``` + +    1-2) 호출방법 + +      (1) 파일에 차트생성에 필요한 form, MainChart, MainConfig 임폴트 +```js +import type { ChartConfig } from "@common/business_components"; +import {MainChart} from "@common/business_components"; +import {CHART_FORM} from "@common/business_components"; +``` +      (2) ChartForm 지정 +```js +/** + * CHART_FORM.BAR : Bar차트 + * CHART_FORM.LINE : Line차트 + * DN : Daughnut차트 +**/ +const chartForm = CHART_FORM.BAR; +``` +      (3) chartData 정의 +``` js +/** + * label : 차트항목 / val : 데이터값 +**/ +const chartData = [ + { label: "January", val: 186}, + { label: "March", val: 237}, + { label: "February", val: 305}, + { label: "April", val: 73}, + { label: "May", val: 209}, + { label: "June", val: 214}, +] +``` +      (4) Chart생성에 필요한 chartConfig 정의 +``` js +/** + * 차트 Config + */ +const chartConfig = chartData.reduce((config,>>element) => { + label: element.label, + config[element.label] = { + color : "hsl(var(--chart-1))" + }; + return config; + }, {} as Record) satisfies ChartConfig; +``` +      (5) Chart 객체 생성 +```html +return ( +
+ +
+ ); +``` +  + +  2. 차트 모듈 구조 + + + + + + + From 8be4a7c086ef328c7ad9d230dd6be670fa808a6d Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Fri, 28 Feb 2025 16:58:50 +0900 Subject: [PATCH 3/4] =?UTF-8?q?README.md=20=EB=B0=8F=20chart.md=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/business_components/README.md | 22 +++++++++++ .../business_components/{ => src}/chart.md | 39 ++----------------- 2 files changed, 25 insertions(+), 36 deletions(-) create mode 100644 packages/common/business_components/README.md rename packages/common/business_components/{ => src}/chart.md (57%) diff --git a/packages/common/business_components/README.md b/packages/common/business_components/README.md new file mode 100644 index 000000000..597f49a5c --- /dev/null +++ b/packages/common/business_components/README.md @@ -0,0 +1,22 @@ +## business_components 패키지 +### 원앤올에서 제공받는 컴포넌트 외에 업무 파트에서 사용할 수 있는 별도 components 패키지지 +  1) 설정 + +    (1) tsconfig.json 'path'에 '@common/business_components' 변수를 추가 +```json +"paths": { + "@/*": ["./*"], + "@common/components/*": ["../../packages/common/components/src/*"], + "@common/components": ["../../packages/common/components/src/index"], + // 작성구문문 + "@common/business_components/*": ["../../packages/common/business_components/src/*"], + "@common/business_components": ["../../packages/common/business_components/src/index"] +} +``` +    (2) package.json 'dependencies'에 '@common/business_components' 추가 +```json +"dependencies": { + "@common/business_components": "workspace:*", + "next": "15.1.7" +}, +``` \ No newline at end of file diff --git a/packages/common/business_components/chart.md b/packages/common/business_components/src/chart.md similarity index 57% rename from packages/common/business_components/chart.md rename to packages/common/business_components/src/chart.md index ceacc3a69..f2d989375 100644 --- a/packages/common/business_components/chart.md +++ b/packages/common/business_components/src/chart.md @@ -2,34 +2,11 @@ ### 공통 모듈 중 Chart를 다양한 테마로 적용시킬 수 있도록 해주는 모듈   1. 차트 모듈 사용법 -    1-1) 설정 - -      (1) tsconfig.json 'path'에 '@common/business_components' 변수를 추가 -```json -"paths": { - "@/*": ["./*"], - "@common/components/*": ["../../packages/common/components/src/*"], - "@common/components": ["../../packages/common/components/src/index"], - // 작성구문문 - "@common/business_components/*": ["../../packages/common/business_components/src/*"], - "@common/business_components": ["../../packages/common/business_components/src/index"] -} -``` -      (2) package.json 'dependencies'에 '@common/business_components' 추가 -```json -"dependencies": { - "@common/business_components": "workspace:*", - "next": "15.1.7" -}, -``` - -    1-2) 호출방법 +    1-1) 호출방법       (1) 파일에 차트생성에 필요한 form, MainChart, MainConfig 임폴트 ```js -import type { ChartConfig } from "@common/business_components"; -import {MainChart} from "@common/business_components"; -import {CHART_FORM} from "@common/business_components"; +import {type ChartConfig, MainChart, CHART_FORM } from "@common/business_components"; ```       (2) ChartForm 지정 ```js @@ -74,14 +51,4 @@ return ( ); -``` -  - -  2. 차트 모듈 구조 - - - - - - - +``` \ No newline at end of file From 86c29bc790fdf7cd5deb8bb9742639947b144756 Mon Sep 17 00:00:00 2001 From: leedj312 Date: Fri, 28 Feb 2025 17:03:39 +0900 Subject: [PATCH 4/4] =?UTF-8?q?form=20=EB=B0=8Ftable=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/package.json | 9 +- .../common/business_components/src/index.css | 11 ++ .../src/ui/form/button.tsx | 56 ++++++ .../business_components/src/ui/form/index.tsx | 176 ++++++++++++++++++ .../business_components/src/ui/form/label.tsx | 24 +++ .../business_components/src/ui/index.ts | 2 + .../src/ui/table/index.tsx | 47 +++++ .../src/ui/table/lib/button.tsx | 56 ++++++ .../src/ui/table/lib/pagination.tsx | 117 ++++++++++++ .../src/ui/table/uiPageNations.tsx | 46 +++++ 10 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 packages/common/business_components/src/index.css create mode 100644 packages/common/business_components/src/ui/form/button.tsx create mode 100644 packages/common/business_components/src/ui/form/index.tsx create mode 100644 packages/common/business_components/src/ui/form/label.tsx create mode 100644 packages/common/business_components/src/ui/table/index.tsx create mode 100644 packages/common/business_components/src/ui/table/lib/button.tsx create mode 100644 packages/common/business_components/src/ui/table/lib/pagination.tsx create mode 100644 packages/common/business_components/src/ui/table/uiPageNations.tsx diff --git a/packages/common/business_components/package.json b/packages/common/business_components/package.json index 39e55ebb6..ca6f67b76 100644 --- a/packages/common/business_components/package.json +++ b/packages/common/business_components/package.json @@ -26,10 +26,17 @@ }, "dependencies": { "@common/components": "workspace:*", + "@hookform/resolvers": "^4.1.2", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-slot": "^1.1.2", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "lucide-react": "^0.474.0", "path": "^0.12.7", + "react-hook-form": "^7.54.2", "recharts": "^2.15.1", - "tailwind-merge": "^3.0.1" + "tailwind-merge": "^3.0.1", + "zod": "^3.24.2" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/packages/common/business_components/src/index.css b/packages/common/business_components/src/index.css new file mode 100644 index 000000000..46896e552 --- /dev/null +++ b/packages/common/business_components/src/index.css @@ -0,0 +1,11 @@ + +@layer base {} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/packages/common/business_components/src/ui/form/button.tsx b/packages/common/business_components/src/ui/form/button.tsx new file mode 100644 index 000000000..36496a287 --- /dev/null +++ b/packages/common/business_components/src/ui/form/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/packages/common/business_components/src/ui/form/index.tsx b/packages/common/business_components/src/ui/form/index.tsx new file mode 100644 index 000000000..4c6d473f4 --- /dev/null +++ b/packages/common/business_components/src/ui/form/index.tsx @@ -0,0 +1,176 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" +import { + Controller, + type ControllerProps, + type FieldPath, + type FieldValues, + FormProvider, + useFormContext, +} from "react-hook-form" + +import { cn } from "@/lib/utils" +import { Label } from "@/ui/form/label" + +const Form = FormProvider + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName +} + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue +) + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +>({ + ...props +}: ControllerProps) => { + return ( + + + + ) +} + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within ") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +} + +type FormItemContextValue = { + id: string +} + +const FormItemContext = React.createContext( + {} as FormItemContextValue +) + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId() + + return ( + +
+ + ) +}) +FormItem.displayName = "FormItem" + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField() + + return ( +
+ + + {headlist.map((head) => ( + {head.title} + ))} + + + + + {publicReuseFacility.map((el: any,index) => ( + + {headlist.map((head) => ( + {el[head.id]} + ))} + + + ))} + + +
+ + + ); + } \ No newline at end of file diff --git a/packages/common/business_components/src/ui/table/lib/button.tsx b/packages/common/business_components/src/ui/table/lib/button.tsx new file mode 100644 index 000000000..b3b79a16f --- /dev/null +++ b/packages/common/business_components/src/ui/table/lib/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "../../../lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/packages/common/business_components/src/ui/table/lib/pagination.tsx b/packages/common/business_components/src/ui/table/lib/pagination.tsx new file mode 100644 index 000000000..2c17f4b45 --- /dev/null +++ b/packages/common/business_components/src/ui/table/lib/pagination.tsx @@ -0,0 +1,117 @@ +import * as React from "react" +import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "../../../lib/utils" +import { type ButtonProps, buttonVariants } from "./button" + +const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => ( +