From 0588bf0d7f15a286693983079b8c0c5f976de533 Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 12 Mar 2025 16:56:47 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=B4=ED=8A=B8=20=EC=83=81?= =?UTF-8?q?=EC=84=B8(=EC=88=98=EC=A0=95)=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B0=94=EC=9D=B8=EB=94=A9=20?= =?UTF-8?q?=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/app/site/register/[id]/page.tsx | 10 ++ apps/cs/app/site/register/page.tsx | 2 - apps/cs/package.json | 1 + apps/cs/src/entities/code/api/code-service.ts | 14 ++ apps/cs/src/entities/code/index.ts | 1 + .../src/entities/code/model/code-interface.ts | 9 + apps/cs/src/entities/code/ui/code-select.tsx | 45 +++++ apps/cs/src/entities/site/api/site-service.ts | 7 + .../src/entities/site/model/site-interface.ts | 26 +++ .../{__mocks__.tsx => table-columns.tsx} | 17 +- .../pages/site/ui/ip-management-dialog.tsx | 8 +- apps/cs/src/pages/site/ui/register-page.tsx | 100 ++++++----- apps/cs/src/pages/site/ui/site-page.tsx | 31 ++-- apps/cs/src/shared/config/api.ts | 1 + packages/common/assets/src/styles/base.css | 2 + packages/common/components/package.json | 1 + .../src/ui/bar-chart/chart.stories.tsx | 2 +- .../src/ui/data-table/data-table.stories.tsx | 2 +- .../components/src/ui/data-table/index.tsx | 13 +- packages/common/components/src/ui/index.ts | 1 + .../common/components/src/ui/input/index.tsx | 2 +- .../src/ui/line-chart/chart.stories.tsx | 31 ++-- .../src/ui/pie-chart/chart.stories.tsx | 53 ++---- .../common/components/src/ui/select/index.tsx | 159 ++++++++++++++++++ .../src/ui/select/select.stories.tsx | 41 +++++ .../common/components/src/ui/table/index.tsx | 2 +- .../common/components/src/ui/table/table.css | 2 +- .../components/src/ui/tree/tree.stories.tsx | 2 +- pnpm-lock.yaml | 70 ++++++++ tailwind.config.preset.ts | 1 + 30 files changed, 529 insertions(+), 127 deletions(-) create mode 100644 apps/cs/app/site/register/[id]/page.tsx delete mode 100644 apps/cs/app/site/register/page.tsx create mode 100644 apps/cs/src/entities/code/api/code-service.ts create mode 100644 apps/cs/src/entities/code/index.ts create mode 100644 apps/cs/src/entities/code/model/code-interface.ts create mode 100644 apps/cs/src/entities/code/ui/code-select.tsx rename apps/cs/src/pages/site/model/{__mocks__.tsx => table-columns.tsx} (74%) create mode 100644 packages/common/components/src/ui/select/index.tsx create mode 100644 packages/common/components/src/ui/select/select.stories.tsx diff --git a/apps/cs/app/site/register/[id]/page.tsx b/apps/cs/app/site/register/[id]/page.tsx new file mode 100644 index 000000000..b1f4d3a16 --- /dev/null +++ b/apps/cs/app/site/register/[id]/page.tsx @@ -0,0 +1,10 @@ +import { RegisterPage as ViewRegisterPage } from "@/pages/site"; + +export default async function RegisterPage({ + params, +}: { + params: Promise<{ id: string }>; +}) { + const { id } = await params; + return ; +} diff --git a/apps/cs/app/site/register/page.tsx b/apps/cs/app/site/register/page.tsx deleted file mode 100644 index a11d0b60c..000000000 --- a/apps/cs/app/site/register/page.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import { RegisterPage } from "@/pages/site"; -export default RegisterPage; diff --git a/apps/cs/package.json b/apps/cs/package.json index 1797b4828..c9c024291 100644 --- a/apps/cs/package.json +++ b/apps/cs/package.json @@ -15,6 +15,7 @@ "@tanstack/react-table": "^8.21.2", "axios": "^1.8.1", "chart.js": "^4.4.8", + "dayjs": "^1.11.13", "js-cookie": "^3.0.5", "next": "15.1.7", "react-chartjs-2": "^5.3.0", diff --git a/apps/cs/src/entities/code/api/code-service.ts b/apps/cs/src/entities/code/api/code-service.ts new file mode 100644 index 000000000..3a789f2aa --- /dev/null +++ b/apps/cs/src/entities/code/api/code-service.ts @@ -0,0 +1,14 @@ +import { client } from "@/shared/api/client"; +import { ENDPOINT } from "@/shared/config/api"; +import type { CodeService, ICode } from "../model/code-interface"; + +export class CodeApiService implements CodeService { + public async getCode(upCd: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.CODE}/${upCd}`, + ); + return response.data; + } +} + +export const CodeApi = new CodeApiService(); diff --git a/apps/cs/src/entities/code/index.ts b/apps/cs/src/entities/code/index.ts new file mode 100644 index 000000000..0b6633f4b --- /dev/null +++ b/apps/cs/src/entities/code/index.ts @@ -0,0 +1 @@ +export { CodeSelect } from "./ui/code-select"; diff --git a/apps/cs/src/entities/code/model/code-interface.ts b/apps/cs/src/entities/code/model/code-interface.ts new file mode 100644 index 000000000..0d066e6da --- /dev/null +++ b/apps/cs/src/entities/code/model/code-interface.ts @@ -0,0 +1,9 @@ +export interface ICode { + lwpoCd: string; + upCd: string; + lwpoCdNm: string; +} + +export interface CodeService { + getCode(upCd: string): Promise; +} diff --git a/apps/cs/src/entities/code/ui/code-select.tsx b/apps/cs/src/entities/code/ui/code-select.tsx new file mode 100644 index 000000000..88c8a1368 --- /dev/null +++ b/apps/cs/src/entities/code/ui/code-select.tsx @@ -0,0 +1,45 @@ +import { useQuery } from "@tanstack/react-query"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@common/components"; +import { ENDPOINT } from "@/shared/config/api"; +import { CodeApi } from "../api/code-service"; + +type CodeSelectProps = { + upCd: string; + value?: string; + defaultValue?: string; + onValueChange?: (value: string) => void; +}; + +function CodeSelect({ upCd, defaultValue, ...props }: CodeSelectProps) { + const { data: code } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.CODE, upCd], + queryFn: () => CodeApi.getCode(upCd), + enabled: !!upCd, + }); + + const defaultValueText = + code?.find((item) => item.lwpoCd === defaultValue)?.lwpoCdNm ?? "선택"; + + return ( + + ); +} + +export { CodeSelect }; diff --git a/apps/cs/src/entities/site/api/site-service.ts b/apps/cs/src/entities/site/api/site-service.ts index 89ba82350..ee2910e18 100644 --- a/apps/cs/src/entities/site/api/site-service.ts +++ b/apps/cs/src/entities/site/api/site-service.ts @@ -4,6 +4,7 @@ import type { ISiteQuery, ISiteInfo, SiteService, + ISiteDetail, } from "../model/site-interface"; export class SiteApiService implements SiteService { @@ -12,7 +13,13 @@ export class SiteApiService implements SiteService { `${ENDPOINT.CMS_SERVICE.SITES}`, { params: query }, ); + return response.data; + } + public async siteDetail(siteId: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.SITES}/${siteId}`, + ); return response.data; } } diff --git a/apps/cs/src/entities/site/model/site-interface.ts b/apps/cs/src/entities/site/model/site-interface.ts index 8ba2da298..005652b1a 100644 --- a/apps/cs/src/entities/site/model/site-interface.ts +++ b/apps/cs/src/entities/site/model/site-interface.ts @@ -12,7 +12,10 @@ export interface ISite { siteNm: string; siteKindCode: string; bscSiteYn: string; + siteAddr: string; useYn: string; + regDt: string; + rgTrNm: string; } export interface ISiteInfo { @@ -44,6 +47,29 @@ export interface ISiteInfo { empty: boolean; } +export interface ISiteDetail { + siteId: string; + siteNm: string; + siteExpln: string; + siteKndCd: string; + siteKindNm: string; + siteAddr: string; + faxNumber: string; + telNo: string; + lwndCn: string; + basicSiteYn: string; + bkmkIcon: string; + useYn: string; + siteSkn: string; + regDt: string; + rgTr: string; + mdfcnDt: string; + mdFr: string; + rgTrNm: string; + mdFrNm: string; +} + export interface SiteService { siteInfo(query: ISiteQuery): Promise; + siteDetail(siteId: string): Promise; } diff --git a/apps/cs/src/pages/site/model/__mocks__.tsx b/apps/cs/src/pages/site/model/table-columns.tsx similarity index 74% rename from apps/cs/src/pages/site/model/__mocks__.tsx rename to apps/cs/src/pages/site/model/table-columns.tsx index 2b55da7d8..ddf211aea 100644 --- a/apps/cs/src/pages/site/model/__mocks__.tsx +++ b/apps/cs/src/pages/site/model/table-columns.tsx @@ -1,3 +1,4 @@ +import dayjs from "dayjs"; import { createColumnHelper } from "@tanstack/react-table"; import type { ISite } from "@/entities/site/model/site-interface"; @@ -16,8 +17,8 @@ const columns = [ id: "siteNm", header: "사이트명", }), - columnHelper.accessor("siteKindCode", { - id: "unknown1", + columnHelper.accessor("siteAddr", { + id: "siteAddr", header: "대표 URL", }), columnHelper.accessor("bscSiteYn", { @@ -30,13 +31,17 @@ const columns = [ header: "사용 여부", cell: (info) => (info.getValue() ? "Y" : "N"), }), - columnHelper.accessor("siteId", { - id: "unknown2", + columnHelper.accessor("rgTrNm", { + id: "rgTrNm", header: "등록자", }), - columnHelper.accessor("siteId", { - id: "ununknown3", + columnHelper.accessor("regDt", { + id: "regDt", header: "등록일", + cell: (info) => { + const date = dayjs(info.getValue()); + return date.format("YYYY-MM-DD"); + }, }), ]; diff --git a/apps/cs/src/pages/site/ui/ip-management-dialog.tsx b/apps/cs/src/pages/site/ui/ip-management-dialog.tsx index 04b71afc7..9f637e3be 100644 --- a/apps/cs/src/pages/site/ui/ip-management-dialog.tsx +++ b/apps/cs/src/pages/site/ui/ip-management-dialog.tsx @@ -26,7 +26,11 @@ type IP = { allowed: boolean; }; -function IPManagementDialog() { +type IPManagementDialogProps = { + triggerDisabled?: boolean; +}; + +function IPManagementDialog({ triggerDisabled }: IPManagementDialogProps) { const [rows, setRows] = useState([]); const [rowSelection, setRowSelection] = useState([]); @@ -72,7 +76,7 @@ function IPManagementDialog() { return ( - + diff --git a/apps/cs/src/pages/site/ui/register-page.tsx b/apps/cs/src/pages/site/ui/register-page.tsx index 3c35ae8e0..0257176ab 100644 --- a/apps/cs/src/pages/site/ui/register-page.tsx +++ b/apps/cs/src/pages/site/ui/register-page.tsx @@ -1,11 +1,10 @@ "use client"; +import { useState } from "react"; +import { SiteApi } from "@/entities/site"; +import { ENDPOINT } from "@/shared/config/api"; import { Button, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, Input, Label, RadioGroup, @@ -16,10 +15,24 @@ import { TableHead, TableRow, } from "@common/components"; +import { useQuery } from "@tanstack/react-query"; +import { CodeSelect } from "@/entities/code"; import { SitePageLayout } from "./layout"; import { IPManagementDialog } from "./ip-management-dialog"; -function RegisterPage() { +function RegisterPage({ siteId }: { siteId: string }) { + const { data: siteDetail } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], + queryFn: () => SiteApi.siteDetail(siteId), + select: (data) => { + setSiteKndCd(data.siteKndCd); + return data; + }, + enabled: !!siteId, + }); + const [siteKndCd, setSiteKndCd] = useState(""); + const [, setSiteSkinCd] = useState(""); + return (
@@ -36,54 +49,38 @@ function RegisterPage() { 사이트 코드 - + 사이트 구분
- - - - - - - 내부 - 외부 - - - - + { + setSiteKndCd(value); + }} + /> +
사이트 디자인 - - - - - - - 라이트 - 다크 - - - + { + setSiteSkinCd(value); + }} + /> @@ -92,6 +89,7 @@ function RegisterPage() { @@ -101,6 +99,7 @@ function RegisterPage() { @@ -110,6 +109,7 @@ function RegisterPage() { @@ -119,6 +119,7 @@ function RegisterPage() { @@ -128,6 +129,7 @@ function RegisterPage() { @@ -137,6 +139,7 @@ function RegisterPage() { @@ -146,13 +149,19 @@ function RegisterPage() { 기본 사이트 여부 - + { + console.log(value); + }} + >
@@ -167,7 +176,12 @@ function RegisterPage() { 사용 여부 - + { + console.log(value); + }} + >
diff --git a/apps/cs/src/pages/site/ui/site-page.tsx b/apps/cs/src/pages/site/ui/site-page.tsx index c13284ce8..46e957985 100644 --- a/apps/cs/src/pages/site/ui/site-page.tsx +++ b/apps/cs/src/pages/site/ui/site-page.tsx @@ -8,12 +8,19 @@ import { useQuery } from "@tanstack/react-query"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { Button, Input, DataTable } from "@common/components"; import { SiteApi } from "@/entities/site/api/site-service"; +import type { ISite, ISiteQuery } from "@/entities/site/model/site-interface"; import { ENDPOINT } from "@/shared/config/api"; -import { columns } from "../model/__mocks__"; +import { columns } from "../model/table-columns"; import { SitePageLayout } from "./layout"; -import type { ISiteQuery } from "@/entities/site/model/site-interface"; function SitePage() { + const router = useRouter(); + const { data: siteInfo, refetch } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.SITES], + queryFn: () => SiteApi.siteInfo(siteQuery), + enabled: false, + }); + const [siteQuery, setSiteQuery] = useState({ siteNm: "", siteKndCd: "", @@ -23,10 +30,10 @@ function SitePage() { sort: [], }); - const { data: siteInfo, refetch } = useQuery({ - queryKey: [ENDPOINT.CMS_SERVICE.SITES], - queryFn: () => SiteApi.siteInfo(siteQuery), - enabled: false, + const table = useReactTable({ + data: siteInfo?.content ?? [], + columns, + getCoreRowModel: getCoreRowModel(), }); const handleSubmit = (e: React.FormEvent) => { @@ -34,15 +41,13 @@ function SitePage() { refetch(); }; - const router = useRouter(); - const table = useReactTable({ - data: siteInfo?.content ?? [], - columns, - getCoreRowModel: getCoreRowModel(), - }); + const handleRowClick = (row: ISite) => { + router.push(`/site/register/${row.siteId}`); + }; useEffect(() => { refetch(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( @@ -71,7 +76,7 @@ function SitePage() {
- +
diff --git a/apps/cs/src/shared/config/api.ts b/apps/cs/src/shared/config/api.ts index 052eea56a..bab8cac7b 100644 --- a/apps/cs/src/shared/config/api.ts +++ b/apps/cs/src/shared/config/api.ts @@ -10,6 +10,7 @@ export const ENDPOINT = { }, CMS_SERVICE: { SITES: "/cms-service/api/v1/sites", + CODE: "/cms-service/api/v1/code/cache", }, }; diff --git a/packages/common/assets/src/styles/base.css b/packages/common/assets/src/styles/base.css index bd9accda9..2d73b09df 100644 --- a/packages/common/assets/src/styles/base.css +++ b/packages/common/assets/src/styles/base.css @@ -23,6 +23,7 @@ --border: #e5e5e5; --input: #e5e5e5; --label: #666666; + --placeholder: #a2a2a2; --ring: #0a0a0a; --chart-1: #2094fa; --chart-2: #00dfe5; @@ -52,6 +53,7 @@ --border: #262626; --input: #262626; --label: #f1f1f1; + --placeholder: #737373; --ring: #d4d4d4; --chart-1: #66b3ff; --chart-2: #66f0f2; diff --git a/packages/common/components/package.json b/packages/common/components/package.json index b9b9f4f40..2bfdb6ba6 100644 --- a/packages/common/components/package.json +++ b/packages/common/components/package.json @@ -34,6 +34,7 @@ "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-radio-group": "^1.2.2", + "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-slider": "^1.2.3", "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-switch": "^1.1.3", diff --git a/packages/common/components/src/ui/bar-chart/chart.stories.tsx b/packages/common/components/src/ui/bar-chart/chart.stories.tsx index 60bd0906f..97fa3be49 100644 --- a/packages/common/components/src/ui/bar-chart/chart.stories.tsx +++ b/packages/common/components/src/ui/bar-chart/chart.stories.tsx @@ -22,7 +22,7 @@ const meta: Meta = { description: { component: ` - [Docs](https://react-chartjs-2.js.org/) - `, +`, }, source: { code: ` 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 d1a4c2142..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 @@ -14,7 +14,7 @@ const meta: Meta = { description: { component: ` - [Docs](https://tanstack.com/table/v8/docs/introduction) - `, +`, }, source: { code: ` diff --git a/packages/common/components/src/ui/data-table/index.tsx b/packages/common/components/src/ui/data-table/index.tsx index 4b0ba901b..8dc30c701 100644 --- a/packages/common/components/src/ui/data-table/index.tsx +++ b/packages/common/components/src/ui/data-table/index.tsx @@ -36,15 +36,22 @@ function THead({ table }: { table: TableType }) { ); } -type TableProps = { table: TableType }; +type TableProps = { + table: TableType; + onRowClick?: (row: T) => void; +}; -function DataTable({ table }: TableProps) { +function DataTable({ table, onRowClick }: TableProps) { return ( {table.getRowModel().rows.map((row) => ( - + onRowClick?.(row.original)} + className={onRowClick ? "cursor-pointer hover:bg-muted" : ""} + > {row.getVisibleCells().map((cell) => { const { meta } = cell.column.columnDef; return ( diff --git a/packages/common/components/src/ui/index.ts b/packages/common/components/src/ui/index.ts index cdc88e163..438c18dbd 100644 --- a/packages/common/components/src/ui/index.ts +++ b/packages/common/components/src/ui/index.ts @@ -15,6 +15,7 @@ export * from "./layout"; export * from "./loading"; export * from "./popover"; export * from "./radio-group"; +export * from "./select"; export * from "./slider"; export * from "./switch"; export * from "./table"; diff --git a/packages/common/components/src/ui/input/index.tsx b/packages/common/components/src/ui/input/index.tsx index bcb03d621..70bb9827c 100644 --- a/packages/common/components/src/ui/input/index.tsx +++ b/packages/common/components/src/ui/input/index.tsx @@ -8,7 +8,7 @@ const Input = React.forwardRef>( = { title: "Chart/Line", @@ -23,7 +22,7 @@ const meta: Meta = { description: { component: ` - [Docs](https://react-chartjs-2.js.org/) - `, +`, }, source: { code: ` @@ -107,7 +106,7 @@ export const Default: Story = { LineElement, Title, Tooltip, - Legend + Legend, ); const options: ChartOptions<"line"> = { @@ -124,29 +123,29 @@ export const Default: Story = { }; const labels = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July' + "January", + "February", + "March", + "April", + "May", + "June", + "July", ]; const data = { labels, datasets: [ { - label: 'Dataset 1', + label: "Dataset 1", data: labels.map(() => faker.number.int({ min: -1000, max: 1000 })), - borderColor: 'rgb(255, 99, 132)', - backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: "rgb(255, 99, 132)", + backgroundColor: "rgba(255, 99, 132, 0.5)", }, { - label: 'Dataset 2', + label: "Dataset 2", data: labels.map(() => faker.number.int({ min: -1000, max: 1000 })), - borderColor: 'rgb(53, 162, 235)', - backgroundColor: 'rgba(53, 162, 235, 0.5)', + borderColor: "rgb(53, 162, 235)", + backgroundColor: "rgba(53, 162, 235, 0.5)", }, ], }; diff --git a/packages/common/components/src/ui/pie-chart/chart.stories.tsx b/packages/common/components/src/ui/pie-chart/chart.stories.tsx index 199878356..0e50d2e22 100644 --- a/packages/common/components/src/ui/pie-chart/chart.stories.tsx +++ b/packages/common/components/src/ui/pie-chart/chart.stories.tsx @@ -1,15 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { - Chart as ChartJS, - ArcElement, - Tooltip, - Legend, - type ChartOptions, -} from "chart.js"; +import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js"; import { Pie } from "react-chartjs-2"; -import { fakerKO as faker } from "@faker-js/faker"; -import { getCssVariableValue } from "../../lib/utils"; const meta: Meta = { title: "Chart/Pie", @@ -19,7 +11,7 @@ const meta: Meta = { description: { component: ` - [Docs](https://react-chartjs-2.js.org/) - `, +`, }, source: { code: ` @@ -83,42 +75,31 @@ type Story = StoryObj; export const Default: Story = { render: () => { - ChartJS.register( - ArcElement, - Tooltip, - Legend, - ); + ChartJS.register(ArcElement, Tooltip, Legend); - const labels = [ - 'Red', - 'Blue', - 'Yellow', - 'Green', - 'Purple', - 'Orange' - ]; + const labels = ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]; const data = { labels, datasets: [ { - label: '# of Votes', + label: "# of Votes", data: [12, 19, 3, 5, 2, 3], backgroundColor: [ - 'rgba(255, 99, 132, 0.2)', - 'rgba(54, 162, 235, 0.2)', - 'rgba(255, 206, 86, 0.2)', - 'rgba(75, 192, 192, 0.2)', - 'rgba(153, 102, 255, 0.2)', - 'rgba(255, 159, 64, 0.2)', + "rgba(255, 99, 132, 0.2)", + "rgba(54, 162, 235, 0.2)", + "rgba(255, 206, 86, 0.2)", + "rgba(75, 192, 192, 0.2)", + "rgba(153, 102, 255, 0.2)", + "rgba(255, 159, 64, 0.2)", ], borderColor: [ - 'rgba(255, 99, 132, 1)', - 'rgba(54, 162, 235, 1)', - 'rgba(255, 206, 86, 1)', - 'rgba(75, 192, 192, 1)', - 'rgba(153, 102, 255, 1)', - 'rgba(255, 159, 64, 1)', + "rgba(255, 99, 132, 1)", + "rgba(54, 162, 235, 1)", + "rgba(255, 206, 86, 1)", + "rgba(75, 192, 192, 1)", + "rgba(153, 102, 255, 1)", + "rgba(255, 159, 64, 1)", ], borderWidth: 1, }, diff --git a/packages/common/components/src/ui/select/index.tsx b/packages/common/components/src/ui/select/index.tsx new file mode 100644 index 000000000..ffd63bb9a --- /dev/null +++ b/packages/common/components/src/ui/select/index.tsx @@ -0,0 +1,159 @@ +"use client"; + +import * as React from "react"; +import * as SelectPrimitive from "@radix-ui/react-select"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; + +import { cn } from "../../lib/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className, + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/packages/common/components/src/ui/select/select.stories.tsx b/packages/common/components/src/ui/select/select.stories.tsx new file mode 100644 index 000000000..41846d17d --- /dev/null +++ b/packages/common/components/src/ui/select/select.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "."; + +const meta: Meta = { + title: "Elements/Select", + component: Select, + parameters: { + docs: { + description: { + component: ` +- [Docs](https://ui.shadcn.com/docs/components/select) +- [API Reference](https://www.radix-ui.com/primitives/docs/components/select#api-reference) +`, + }, + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => ( + + ), +}; diff --git a/packages/common/components/src/ui/table/index.tsx b/packages/common/components/src/ui/table/index.tsx index 425fdba0c..e96ea7e4d 100644 --- a/packages/common/components/src/ui/table/index.tsx +++ b/packages/common/components/src/ui/table/index.tsx @@ -63,7 +63,7 @@ const TableRow = React.forwardRef< = { description: { component: ` - [Docs](https://github.com/minop1205/react-dnd-treeview/blob/next/README.md) - `, +`, }, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1c113792..e99e6c0c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: chart.js: specifier: ^4.4.8 version: 4.4.8 + dayjs: + specifier: ^1.11.13 + version: 1.11.13 js-cookie: specifier: ^3.0.5 version: 3.0.5 @@ -148,6 +151,9 @@ importers: '@radix-ui/react-radio-group': specifier: ^1.2.2 version: 1.2.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-select': + specifier: ^2.1.6 + version: 2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-slider': specifier: ^1.2.3 version: 1.2.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) @@ -2077,6 +2083,46 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@radix-ui/react-select@2.1.6(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==} + peerDependencies: + '@types/react': ^18.3.18 + '@types/react-dom': ^18.3.5 + react: ^18.3.1 + react-dom: ^18.3.1 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/number': 1.1.0 + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) + aria-hidden: 1.2.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.6.3(@types/react@18.3.18)(react@18.3.1) + dev: false + /@radix-ui/react-slider@1.2.3(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-nNrLAWLjGESnhqBqcCNW4w2nn7LxudyMzeB6VgdyAnFLC6kfQgnAjSL2v6UkQTnDctJBlxrmxfplWS4iYjdUTw==} peerDependencies: @@ -2269,6 +2315,26 @@ packages: react: 18.3.1 dev: false + /@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==} + peerDependencies: + '@types/react': ^18.3.18 + '@types/react-dom': ^18.3.5 + react: ^18.3.1 + react-dom: ^18.3.1 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: false + /@radix-ui/rect@1.1.0: resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} dev: false @@ -3984,6 +4050,10 @@ packages: resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} dev: false + /dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dev: false + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: diff --git a/tailwind.config.preset.ts b/tailwind.config.preset.ts index dc8cf1743..ee341683e 100644 --- a/tailwind.config.preset.ts +++ b/tailwind.config.preset.ts @@ -41,6 +41,7 @@ export default { border: "var(--border)", input: "var(--input)", label: "var(--label)", + placeholder: "var(--placeholder)", ring: "var(--ring)", chart: { 1: "var(--chart-1)",