Skip to content

Commit

Permalink
[Feat]:create TimesheetCard component with customizable props (#3191)
Browse files Browse the repository at this point in the history
* feat:create TimesheetCard component with customizable props

* refact: code

* refact: code

* fix: cspell

* feat(timesheet): add filter components

* fix: deep scan

* fix: build
  • Loading branch information
Innocent-Akim authored Oct 28, 2024
1 parent 45fb45e commit 77dbebe
Show file tree
Hide file tree
Showing 16 changed files with 455 additions and 20 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@
"tailess",
"Tailess",
"tailwindcss",
"timesheet-viewMode",
"tanstack",
"taskid",
"taskstatus",
Expand Down
9 changes: 9 additions & 0 deletions apps/web/app/[locale]/timesheet/components/CalendarView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'

export function CalendarView() {
return (
<div className='grow h-full w-full bg-[#FFFFFF]'>

</div>
)
}
35 changes: 35 additions & 0 deletions apps/web/app/[locale]/timesheet/components/FilterWithStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { HTMLAttributes } from 'react';
import { Button } from 'lib/components';
import { clsxm } from '@app/utils';

export type FilterStatus = "All Tasks" | "Pending" | "Approved" | "Rejected";
export function FilterWithStatus({
activeStatus,
onToggle,
className
}: {
activeStatus: FilterStatus;
onToggle: (status: FilterStatus) => void;
className?: HTMLAttributes<HTMLDivElement>
}) {
const buttonData: { label: FilterStatus; count: number; icon: React.ReactNode }[] = [
{ label: 'All Tasks', count: 46, icon: <i className="icon-all" /> },
{ label: 'Pending', count: 12, icon: <i className="icon-pending" /> },
{ label: 'Approved', count: 28, icon: <i className="icon-approved" /> },
{ label: 'Rejected', count: 6, icon: <i className="icon-rejected" /> },
];

return (
<div className={clsxm('grid grid-cols-4 h-[2.4rem] items-center justify-start bg-[#e2e8f0aa] rounded-xl w-full', className)}>
{buttonData.map(({ label, count, icon }, index) => (
<Button
key={index}
className={clsxm('group flex items-center justify-start h-[2.4rem] rounded-xl border dark:bg-dark--theme-light dark:border-gray-700 bg-[#e2e8f0aa] text[#71717A]', `${activeStatus === label ? "text-primary bg-white shadow-lg font-bold" : ""}`)}
onClick={() => onToggle(label)}>
<span className={clsxm('font-medium ml-1 text-[#71717A]', `${activeStatus === label ? "text-primary" : ""}`)}>{label}</span>
<span className='font-medium ml-1 text-[#71717A]'>{count}</span>
</Button>
))}
</div>
);
}
99 changes: 99 additions & 0 deletions apps/web/app/[locale]/timesheet/components/FrequencySelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from "react";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@components/ui/select"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@components/ui/dropdown-menu"
import { Button } from "lib/components/button";

export function FrequencySelect() {
const [selectedValue, setSelectedValue] = React.useState<string | undefined>(undefined);

const handleSelectChange = (value: string) => {
setSelectedValue(value);
};

return (
<Select
value={selectedValue}
onValueChange={handleSelectChange}>
<SelectTrigger className="w-[180px] border border-gray-200 dark:border-gray-700 bg-white dark:bg-dark--theme-light focus:ring-2 focus:ring-transparent">
<SelectValue placeholder="Select a daily" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="daily">Daily</SelectItem>
<SelectItem value="weekly">Weekly</SelectItem>
<SelectItem value="monthly">Monthly</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
);
}




export const FilterTaskActionMenu = () => {
// const handleCopyPaymentId = () => navigator.clipboard.writeText(idTasks);
return (
<DropdownMenu open={true} >
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0 text-sm sm:text-base">
{/* <span className="sr-only">Open menu</span> */}
<span>Today</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="z-50">
<DropdownMenuItem className="cursor-pointer" >
Today
</DropdownMenuItem>
<DropdownMenuItem className="cursor-pointer" >
Last 7 days
</DropdownMenuItem>
<DropdownMenuItem className="cursor-pointer" >
Last 30 days
</DropdownMenuItem>
<DropdownMenuItem className="cursor-pointer" >
This year (2024)
{/* ({new Date().getFullYear()}) */}
</DropdownMenuItem>
{/* <DropdownMenuSeparator /> */}
<CustomDateRange />
</DropdownMenuContent>
</DropdownMenu>
);
};

export const CustomDateRange = () => {
return (
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<span>Custom Date Range</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem className="cursor-pointer">
<div className="flex items-center gap-3">
<div className="h-1 w-1 rounded-full bg-black dark:bg-white"></div>
<span>Calendar</span>
</div>
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
)
}
65 changes: 65 additions & 0 deletions apps/web/app/[locale]/timesheet/components/TimesheetCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

import { clsxm } from '@app/utils';
import { ArrowRightIcon } from 'assets/svg';
import { Button, Card } from 'lib/components';
import React, { ReactNode } from 'react'

interface ITimesheetCard {
title?: string;
date?: string
description?: string;
hours?: string;
count?: number;
color?: string;
icon?: ReactNode;
classNameIcon?: string
onClick?: () => void;
}


export function TimesheetCard({ ...props }: ITimesheetCard) {
const { icon, title, date, description, hours, count, onClick, classNameIcon } = props;
return (
<Card
aria-label={`Timesheet card for ${title}`}
shadow='custom'
className='w-full h-[175px] rounded-md border border-gray-200 flex gap-8 shadow shadow-gray-100 p-3'>
<div className='!gap-8 w-full space-y-4 '>
<div className='flex flex-col gap-1 justify-start items-start'>
<h1 className='text-2xl md:text-[25px] font-bold truncate w-full'>{hours ?? count}</h1>
<h2 className='text-base md:text-[16px] font-medium text-[#282048] truncate w-full'>{title}</h2>
<span className='text-sm md:text-[14px] text-[#3D5A80] truncate w-full'>{date ?? description}</span>
</div>
<Button
variant='outline'
className={clsxm(
'h-9 px-3 py-2',
'border border-gray-200',
'text-[#282048] text-sm',
'flex items-center',
'hover:bg-gray-50 focus:ring-2 focus:ring-offset-2 focus:ring-gray-200'
)}
aria-label="View timesheet details"
onClick={onClick}>
<span>View Details</span>
<ArrowRightIcon className={clsxm(
'h-6 w-6',
'text-[#282048] dark:text-[#6b7280]'
)} />
</Button>
</div>
<Card
shadow='custom'
className={clsxm(
'h-7 w-7',
'flex items-center justify-center',
'text-white font-bold text-sm',
'shadow-lg',
classNameIcon
)}
aria-hidden="true">
{icon}
</Card>
</Card>
)
}
39 changes: 39 additions & 0 deletions apps/web/app/[locale]/timesheet/components/TimesheetFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react'
import { FilterWithStatus } from './FilterWithStatus'
import { FrequencySelect } from '.';
import { Button } from 'lib/components';
import { SettingFilterIcon } from 'assets/svg';

export function TimesheetFilter() {
return (
<div className="grid grid-cols-3 w-full">
<div className="col-span-1">
<FilterWithStatus
activeStatus="Rejected"
onToggle={(label) => {
console.log(label)
}}
/>
</div>
<div className="col-span-1"></div>
<div className="col-span-1">
<div className='flex gap-2'>
<FrequencySelect />
<button
onClick={() => null}
className='flex items-center justify-center h-10 rounded-lg bg-white dark:bg-dark--theme-light border dark:border-gray-700 hover:bg-white p-3 gap-2' >
<SettingFilterIcon className="text-gray-700 dark:text-white w-3.5" strokeWidth="1.8" />
<span className="text-gray-700 dark:text-white">Filter</span>
</button>
<Button
onClick={() => null}
variant='outline'
className='bg-primary/5 dark:bg-primary-light h-10 w-[2.5rem] font-medium'>
Add Time
</Button>
</div>
</div>
</div>

)
}
10 changes: 10 additions & 0 deletions apps/web/app/[locale]/timesheet/components/TimesheetView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { DataTableTimeSheet } from 'lib/features/integrations/calendar'
import React from 'react'

export function TimesheetView() {
return (
<div className='grow h-full w-full bg-[#FFFFFF]'>
<DataTableTimeSheet />
</div>
)
}
6 changes: 6 additions & 0 deletions apps/web/app/[locale]/timesheet/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './TimesheetCard';
export * from './TimesheetView';
export * from './CalendarView';
export * from './TimesheetFilter';
export * from './FrequencySelect';
export * from './FilterWithStatus';
Loading

0 comments on commit 77dbebe

Please sign in to comment.