Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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: 1 addition & 1 deletion frontend/src/assets/Icons/chevron-back.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 9 additions & 7 deletions frontend/src/components/data-table/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import {
interface DataTableProps<TData> {
groupBy?: (row: TData) => string;
enableGroupSelection?: boolean;
height?: number;
blankFallbackText?: string;
}

const DataTable = <TData,>({
groupBy,
height,
enableGroupSelection = true,
blankFallbackText,
}: DataTableProps<TData>) => {
const { table, dispatch } = useDataTable();
const rows = table.getRowModel().rows as Row<TData>[];
Expand Down Expand Up @@ -60,8 +60,8 @@ const DataTable = <TData,>({
); // dispatch가 바뀌지 않는 한 함수 재사용

return (
<Table height={height}>
<TableHeader className="sticky top-0 z-10">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
Expand Down Expand Up @@ -151,12 +151,14 @@ const DataTable = <TData,>({
);
})
) : (
<TableRow>
<TableRow className="hover:bg-background-normal!">
<TableCell
colSpan={table.getVisibleLeafColumns().length}
className="h-24 text-center"
className="text-center"
>
No results.
<h1 className="headline1-medium text-label-alternative">
{blankFallbackText || '데이터가 없습니다'}
</h1>
</TableCell>
</TableRow>
)}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/data-table/DataTableProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const DataTableProvider = <TData, TValue = unknown>({
} as DataTableContextType<unknown>
}
>
{children}
<div className="flex min-h-0 flex-1 flex-col">{children}</div>
</DataTableContext.Provider>
);
};
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/components/data-table/ImportToFolderBar.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

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

해당 컴포넌트를 띄워보니까 밑에 약간 잘리는데,, 확인 부탁드려요.

Image

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

이거 z값 문제라서 다른 issue에서 전체적으로 z값 통일 작업중입니다. 이번 pr에서는 넘어갈게요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useDataTable } from '@/components/data-table/context';

import { Icons } from '@/assets';

const Divider = () => <div className="bg-line-solid-normal/30 h-6 w-px" />;

const ImportToFolderBar = () => {
const { table, tableState } = useDataTable();
const selectedRows = table.getFilteredSelectedRowModel().rows;

if (!tableState.selectionMode) return null;

const handleImportToFolder = () => {};

return (
<div className="bg-background-normal body2-normal-bold rounded-modal-12 shadow-semantic-strong fixed bottom-30 left-1/2 w-125 -translate-x-1/2 truncate px-4 py-2.75">
<div className="flex items-center gap-4">
<span className="mr-auto">{selectedRows.length}개 선택됨</span>
<button
onClick={handleImportToFolder}
className="label1-normal-medium text-primary-normal"
>
현재 폴더에 추가하기
</button>
<Divider />
<Icons.Close height={20} width={20} />
</div>
</div>
);
};

export default ImportToFolderBar;
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const SelectionActionButton = ({
);
};

const SelectionActionProvider = () => {
const SelectionActionBar = () => {
const { table, tableState } = useDataTable();
const selectedRows = table.getFilteredSelectedRowModel().rows;

Expand Down Expand Up @@ -57,4 +57,4 @@ const SelectionActionProvider = () => {
);
};

export default SelectionActionProvider;
export default SelectionActionBar;
4 changes: 2 additions & 2 deletions frontend/src/components/layout/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ const BottomSheet = ({
exit={{ y: '100%' }}
transition={{ type: 'spring', damping: 25, stiffness: 200 }}
className={cn(
`bg-background-normal fixed right-[12vh] bottom-0 left-[18vh] z-50 h-[80vh] rounded-t-2xl ${className}`,
`bg-background-normal fixed right-[12vh] bottom-0 left-[18vh] z-50 flex h-[80vh] flex-col rounded-t-2xl px-2 ${className}`,
)}
>
<div className="bg-cool-neutral-95 mx-auto my-3 h-1.5 w-12 rounded-full" />
<div className="bg-cool-neutral-95 mx-auto my-2 h-1.5 w-12 shrink-0 rounded-full" />
{children}
</motion.div>
</>
Expand Down
11 changes: 3 additions & 8 deletions frontend/src/components/ui/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@ import * as React from 'react';

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

function Table({
className,
height,
...props
}: React.ComponentProps<'table'> & { height?: number }) {
function Table({ ...props }: React.ComponentProps<'table'>) {
return (
<div
data-slot="table-container"
className={cn('w-full overflow-auto', className)}
style={{ height }}
className="scrollbar relative min-h-0 w-full flex-1 overflow-y-auto"
>
<table data-slot="table" className="w-full" {...props} />
</div>
Expand All @@ -23,7 +18,7 @@ function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
<thead
data-slot="table-header"
className={cn(
'[&_tr]:border-line-solid-neutral caption1-medium bg-background-normal',
'[&_tr]:border-line-solid-neutral caption1-medium bg-background-normal sticky top-0 z-20',
className,
)}
{...props}
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/pages/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ const DemoSection = () => {
<div className="shadow-semantic-subtle h-fit min-w-0 flex-1 rounded-2xl px-2 py-4">
<DataTableProvider columns={columns} data={data}>
<DataTable
height={480}
enableGroupSelection={false}
groupBy={(row: Expense) =>
new Date(row.date).toLocaleDateString('ko-KR', {
Expand All @@ -211,7 +210,6 @@ const DemoSection = () => {
<div className="shadow-semantic-subtle h-fit min-w-0 flex-1 rounded-2xl px-2 py-4">
<DataTableProvider columns={columns} data={data}>
<DataTable
height={480}
enableGroupSelection={false}
groupBy={(row: Expense) =>
new Date(row.date).toLocaleDateString('ko-KR', {
Expand Down
126 changes: 126 additions & 0 deletions frontend/src/pages/TravelDetailPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { useState } from 'react';
import { Link } from '@tanstack/react-router';

import Button from '@/components/common/Button';
import Divider from '@/components/common/Divider';
import { DataTable } from '@/components/data-table/DataTable';
import { DataTableFilterProvider } from '@/components/data-table/DataTableFilter';
import DataTableProvider from '@/components/data-table/DataTableProvider';
import CategoryFilter from '@/components/data-table/filters/CategoryFilter';
import DateFilter from '@/components/data-table/filters/DateFilter';
import MerchantFilter from '@/components/data-table/filters/MerchantFilter';
import MethodFilter from '@/components/data-table/filters/MethodFilter';
import SortDropdown from '@/components/data-table/filters/SortDropdown';
import ImportToFolderBar from '@/components/data-table/ImportToFolderBar';
import SelectionActionBar from '@/components/data-table/SelectionActionBar';
import { columns } from '@/components/home-page/columns';
import ExpenseCard from '@/components/home-page/ExpenseCard';
import { type Expense, getData } from '@/components/landing-page/dummy';
import BottomSheet from '@/components/layout/BottomSheet';

import { Icons } from '@/assets';

const TripSummary = () => {
return (
<div className="flex flex-col gap-4">
<div className="flex items-center gap-2.5">
<Link to="/travel">
<Icons.ChevronBack className="text-label-normal size-6" />
</Link>
<span className="heading2-bold text-label-normal">뉴욕 보스턴</span>
</div>
<div className="flex gap-1.5">
<span className="body1-normal-medium text-label-normal">
2026.01.21 - 2026.01.26
</span>
<span className="body1-normal-medium text-label-alternative">
5박 6일
</span>
</div>
</div>
);
};

const TravelDetailPage = () => {
const [isBottomSheetOpen, setBottomSheetOpen] = useState(false);

const data = getData();
return (
<div className="flex h-full flex-col px-30 pt-8">
<div className="mb-10 flex items-end gap-4">
<TripSummary />
<Divider style="vertical" className="h-15" />
<ExpenseCard
label="총 지출"
baseCountryCode="KR"
baseCountryAmount={1402432}
localCountryCode="US"
localCountryAmount={12232}
/>
<div className="flex-1" />
<Button variant="outlined" size="md">
위젯 편집하기
</Button>
</div>

<div className="bg-background-normal rounded-modal-16 flex-1 rounded-b-none px-2 py-4 shadow">
<DataTableProvider columns={columns} data={[]}>
<DataTableFilterProvider>
<DateFilter />
<MerchantFilter />
<CategoryFilter />
<MethodFilter />
<div className="flex-1" />
<SortDropdown />
<Button
variant="solid"
size="md"
onClick={() => setBottomSheetOpen(true)}
>
지출 내역 불러오기
</Button>
</DataTableFilterProvider>
<DataTable
groupBy={(row: Expense) =>
new Date(row.date).toLocaleDateString('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
})
}
blankFallbackText={'여행 지출 내역을 추가해주세요'}
/>
<SelectionActionBar />
</DataTableProvider>
</div>
<BottomSheet
isOpen={isBottomSheetOpen}
onClose={() => setBottomSheetOpen(false)}
>
<DataTableProvider columns={columns} data={data}>
<DataTableFilterProvider>
<DateFilter />
<MerchantFilter />
<CategoryFilter />
<MethodFilter />
<div className="flex-1" />
<SortDropdown />
</DataTableFilterProvider>
<DataTable
groupBy={(row: Expense) =>
new Date(row.date).toLocaleDateString('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
})
}
blankFallbackText={'여행 지출 내역을 추가해주세요'}
/>
<ImportToFolderBar />
</DataTableProvider>
</BottomSheet>
</div>
);
};

export default TravelDetailPage;
31 changes: 20 additions & 11 deletions frontend/src/pages/TravelPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Link } from '@tanstack/react-router';

import Button from '@/components/common/Button';
import FolderCard from '@/components/travel-page/FolderCard';

Expand All @@ -6,6 +8,7 @@ import { COUNTRY_CODE } from '@/data/countryCode';

const folderMap = [
{
travelId: 0,
label: '뉴욕 보스턴',
dateRange: '2026.01.21 - 2026.01.26',
localCountryCode: COUNTRY_CODE.US,
Expand All @@ -15,6 +18,7 @@ const folderMap = [
imageUrl: SeoulImage,
},
{
travelId: 1,
label: '뉴욕 보스턴',
dateRange: '2026.01.21 - 2026.01.26',
localCountryCode: COUNTRY_CODE.KR,
Expand All @@ -41,17 +45,22 @@ const TravelPage = () => {
</Button>
</div>
<div className="bg-background-normal rounded-modal-8 shadow-semantic-subtle flex min-h-0 flex-1 flex-wrap gap-9 overflow-y-auto p-16">
{folderMap.map((folder, index) => (
<FolderCard
key={index}
label={folder.label}
dateRange={folder.dateRange}
localCountryCode={folder.localCountryCode}
localCountryAmount={folder.localCountryAmount}
baseCountryCode={folder.baseCountryCode}
baseCountryAmount={folder.baseCountryAmount}
imageUrl={folder.imageUrl}
/>
{folderMap.map((folder) => (
<Link
to={`/travel/$travelId`}
key={folder.travelId}
params={{ travelId: folder.travelId.toString() }}
>
<FolderCard
label={folder.label}
dateRange={folder.dateRange}
localCountryCode={folder.localCountryCode}
localCountryAmount={folder.localCountryAmount}
baseCountryCode={folder.baseCountryCode}
baseCountryAmount={folder.baseCountryAmount}
imageUrl={folder.imageUrl}
/>
</Link>
))}
</div>
</div>
Expand Down
Loading
Loading