Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.5",
"@radix-ui/react-dropdown-menu": "^2.1.5",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.7",
"@tanstack/react-table": "^8.21.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.471.0",
Expand Down
107 changes: 107 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/src/app/LayoutContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function LayoutContent({ children }: { children: React.ReactNode }) {

return (
<SidebarProvider>
<div className="flex h-screen bg-background text-foreground">
<div className="flex h-screen w-full bg-background text-foreground">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flex size-full bg-background text-foreground
이면 충분할것 같네요

<Sidebar collapsible="icon">
<SidebarHeader className="flex h-12 w-full flex-row items-center gap-0">
<Image
Expand Down
15 changes: 13 additions & 2 deletions frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { FlagIcon } from 'lucide-react';

import { columns } from '@/constants/featureFlagColumns';
import { TanstackTable } from '@/components/TanstackTable';
import { ExampleData } from '@/constants/tableMockDatat';

export default function Home() {
return (
<div>
<h1>Light Switch</h1>
<div className="flex size-full flex-col gap-5 p-3">
<header className="flex items-center gap-3">
<FlagIcon size={20} />
<span className="text-xl font-semibold">Feature Flag Management</span>
</header>

<TanstackTable columns={columns} data={ExampleData} />
</div>
);
}
130 changes: 130 additions & 0 deletions frontend/src/components/TanstackTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
'use client';
import {
ColumnDef,
flexRender,
getCoreRowModel,
getPaginationRowModel,
useReactTable,
getSortedRowModel,
PaginationState,
} from '@tanstack/react-table';
import { useState } from 'react';

import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { Button } from '@/components/ui/button';
import { FeatureFlagTableType } from '@/types/types';

export interface DataTableProps<TData extends FeatureFlagTableType, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}

export function TanstackTable<TData extends FeatureFlagTableType, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 9,
});

const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
state: {
pagination,
},
onPaginationChange: setPagination,
});

return (
<div className="flex w-[95%] flex-col items-center">
<div className="w-full rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && 'selected'}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex w-full items-center justify-between space-x-2 py-4">
{`${table.getFilteredSelectedRowModel().rows.length} of ${table.getFilteredRowModel().rows.length} row(s) selected`}
<div className="flex items-center justify-between">
<span className="text-sm">
{`Page ${pagination.pageIndex + 1} of ${table.getPageCount()}`}
</span>
<div className="flex items-center justify-between">
<Button
variant="outline"
size="sm"
onClick={table.previousPage}
disabled={pagination.pageIndex === 0}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={table.nextPage}
disabled={pagination.pageIndex >= table.getPageCount() - 1}
>
Next
</Button>
</div>
</div>
</div>
</div>
);
}
30 changes: 30 additions & 0 deletions frontend/src/components/ui/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use client';

import * as React from 'react';
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
import { Check } from 'lucide-react';

import { cn } from '@/lib/utils';

const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
'peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn('flex items-center justify-center text-current')}
>
<Check className="size-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;

export { Checkbox };
Loading
Loading