Style estimation session list
This commit is contained in:
parent
517bc11c56
commit
0c158a4b22
|
@ -0,0 +1,29 @@
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface CardProps {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Card: React.FC<CardProps> = ({ title, description, onClick }) => {
|
||||||
|
const className = classNames(
|
||||||
|
'p-4 border rounded-lg shadow-sm transition',
|
||||||
|
{
|
||||||
|
'hover:bg-gray-100 dark:hover:bg-nero-800 cursor-pointer': onClick,
|
||||||
|
'cursor-default': !onClick,
|
||||||
|
},
|
||||||
|
'border-gray-300 dark:border-nero-700',
|
||||||
|
'bg-white dark:bg-nero-900',
|
||||||
|
'text-gray-800 dark:text-nero-200',
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={className} onClick={onClick}>
|
||||||
|
<h3 className="text-lg font-bold">{title}</h3>
|
||||||
|
<p className="mt-2">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Card;
|
|
@ -0,0 +1,41 @@
|
||||||
|
interface GridListProps<T> {
|
||||||
|
items: T[];
|
||||||
|
colNum: number;
|
||||||
|
onAddItem: () => void;
|
||||||
|
itemComponent: React.ComponentType<{ item: T }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddItemButton = ({ onAddItem }: { onAddItem: () => void }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={onAddItem}
|
||||||
|
className="flex cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-gray-400 hover:border-gray-600"
|
||||||
|
>
|
||||||
|
<span className="text-gray-500">+ Add Item</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GridList = <T,>({
|
||||||
|
items,
|
||||||
|
colNum,
|
||||||
|
onAddItem,
|
||||||
|
itemComponent: ItemComponent,
|
||||||
|
}: GridListProps<T>) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`grid gap-4`}
|
||||||
|
style={{
|
||||||
|
gridTemplateColumns: `repeat(${colNum}, minmax(0, 1fr))`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{onAddItem && <AddItemButton onAddItem={onAddItem} />}
|
||||||
|
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<ItemComponent key={index} item={item} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GridList;
|
|
@ -1,4 +1,6 @@
|
||||||
import Input from './Input';
|
import Input from './Input';
|
||||||
import Button, { ButtonColor } from './Button';
|
import Button, { ButtonColor } from './Button';
|
||||||
|
import GridList from './GridList';
|
||||||
|
import Card from './Card';
|
||||||
|
|
||||||
export { Input, Button, ButtonColor };
|
export { Input, Button, ButtonColor, GridList, Card };
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import reactLogo from '../assets/react.svg';
|
import reactLogo from '../assets/react.svg';
|
||||||
import viteLogo from '/vite.svg';
|
import viteLogo from '/vite.svg';
|
||||||
import './Home.css';
|
import './Home.css';
|
||||||
import { Link } from '@tanstack/react-router';
|
import { getRouteApi, Link } from '@tanstack/react-router';
|
||||||
import { useUser } from '../lib/context/user';
|
import { useUser } from '../lib/context/user';
|
||||||
import { useEstimationSessions } from '../lib/context/estimationSession';
|
import { useEstimationSessions } from '../lib/context/estimationSession';
|
||||||
|
import { Card, GridList } from '../components';
|
||||||
|
|
||||||
|
const route = getRouteApi('/');
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
|
const navigate = route.useNavigate();
|
||||||
const estimationSessions = useEstimationSessions();
|
const estimationSessions = useEstimationSessions();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -33,11 +37,28 @@ function Home() {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p>Estimation sessions</p>
|
<p>Estimation sessions</p>
|
||||||
{estimationSessions?.current.map((session) => (
|
<GridList
|
||||||
<Link key={session.$id} to={`/estimate/session/${session.$id}`}>
|
colNum={2}
|
||||||
{session.Name}
|
items={estimationSessions?.current ?? []}
|
||||||
</Link>
|
itemComponent={({ item }) => (
|
||||||
))}
|
<Card
|
||||||
|
key={item.$id}
|
||||||
|
title={item.Name}
|
||||||
|
description={item.$id}
|
||||||
|
onClick={() => {
|
||||||
|
navigate({
|
||||||
|
to: '/estimate/session/$sessionId',
|
||||||
|
params: { sessionId: item.$id },
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
onAddItem={() =>
|
||||||
|
navigate({
|
||||||
|
to: '/estimate/new',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,22 @@
|
||||||
export default {
|
export default {
|
||||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {
|
||||||
|
colors: {
|
||||||
|
nero: {
|
||||||
|
50: '#f7f7f7',
|
||||||
|
100: '#e1e1e1',
|
||||||
|
200: '#cfcfcf',
|
||||||
|
300: '#a8a8a8',
|
||||||
|
400: '#737373',
|
||||||
|
500: '#4e4e4e',
|
||||||
|
600: '#383838',
|
||||||
|
700: '#2f2f2f',
|
||||||
|
800: '#282828',
|
||||||
|
900: '#242424',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue