Skip to content

Commit

Permalink
fix: refactor components
Browse files Browse the repository at this point in the history
  • Loading branch information
AlanMamphs committed Nov 3, 2023
1 parent daee340 commit 31c56fd
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 193 deletions.
61 changes: 41 additions & 20 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,49 @@
import { PropsWithChildren, ReactNode } from 'react';

export const CardImage = (props: { image: string }) => (
<div className="h-44 w-full">
<img className="max-h-44 max-w-full mx-auto" src={props.image} />
</div>
);

export const CardHeader = (
props: PropsWithChildren<{ header?: ReactNode }>
) => (
<h3 className="text-md h-8 whitespace-nowrap overflow-hidden text-ellipsis">
{props.header ?? props.children}
</h3>
);

export const CardDescription = (
props: PropsWithChildren<{ description?: ReactNode; title?: string }>
) => (
<p
className="text-sm whitespace-nowrap overflow-hidden text-ellipsis h-8"
title={props.title}
>
{props.description ?? props.children}
</p>
);

export const Card = (props: {
header: string;
image: string;
brands: string;
isActive?: boolean;
header?: string;
image?: string;
description?: string;
active?: boolean;
}) => (
<div
className={`bg-white rounded-md shadow-2xl p-4 max-h-[40rem] h-full hover:bg-gray-100 dark:text-black center ${
props.isActive ? 'border-4 border-indigo-500' : ''
props.active ? 'border-4 border-indigo-500' : ''
}`}
>
<div className="max-h-44 w-full">
<img className="max-h-44 max-w-full mx-auto" src={props.image} />
</div>
<h3
className="text-md h-8 whitespace-nowrap overflow-hidden text-ellipsis"
title={props.header}
>
{props.header}
</h3>
<p
className="text-sm whitespace-nowrap overflow-hidden text-ellipsis h-8"
title={props.brands}
>
{props.brands}
</p>
{props.image && <CardImage image={props.image} />}
{props.header && <CardHeader header={props.header} />}
{props.description && <CardDescription description={props.description} />}
</div>
);

Card.CardHeader = CardHeader;
Card.CardDescription = CardDescription;
Card.CardImage = CardImage;

export default Card;
35 changes: 35 additions & 0 deletions src/components/CloseButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { PropsWithChildren } from 'react';

export const CloseSVG = () => (
<svg
className="w-3 h-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 14 14"
>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
/>
</svg>
);

export const CloseButton = (
props: PropsWithChildren<{
onClick: () => void;
}>
) => (
<button
onClick={props.onClick}
type="button"
className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ml-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
data-modal-hide="default-modal"
>
<CloseSVG />
<span className="sr-only">Close modal</span>
</button>
);
30 changes: 29 additions & 1 deletion src/components/Container.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
import { PropsWithChildren } from 'react';
import { CloseButton } from './CloseButton';

export const Container = (props: PropsWithChildren) => (
export const GridContainer = (props: PropsWithChildren) => (
<div className="w-full m-auto grid gap-4 grid-cols-auto-fit-10rem mt-4 dark:text-white">
{props.children}
</div>
);

export const Header = (props: PropsWithChildren) => (
<h3 className="text-xl font-semibold text-gray-900 dark:text-white">
{props.children}
</h3>
);

export const FlexContainer = ({
header,
onClose,
children,
}: PropsWithChildren<{
header?: string;
onClose?: () => void;
}>) => (
<div className="flex-1 text-gray-900 dark:text-white">
<div
className={
'flex items-start justify-between p-4 border-b rounded-t dark:text-white '
}
>
<Header>{header}</Header>
{onClose && <CloseButton onClick={onClose} />}
</div>
{children}
</div>
);
3 changes: 2 additions & 1 deletion src/components/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const Pagination = ({ totalPages }: { totalPages: number }) => {
<li>
<button
disabled={currentPage === 1}
onClick={() => handlePageChange(currentPage - 1)}
className="flex items-center justify-center px-3 h-8 ml-0 leading-tight text-gray-500 bg-white border border-gray-300 rounded-l-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>
Previous
Expand Down Expand Up @@ -98,7 +99,7 @@ export const Pagination = ({ totalPages }: { totalPages: number }) => {
<li>
<button
disabled={currentPage === totalPages}
onClick={() => handlePageChange(currentPage - 1)}
onClick={() => handlePageChange(currentPage + 1)}
className="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-r-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>
Next
Expand Down
119 changes: 71 additions & 48 deletions src/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,75 @@
import { ReactNode } from 'react';
import { PropsWithChildren } from 'react';

export const Table = (props: {
headers?: string[];
data: { id: string | number; value: string | ReactNode }[][];
}) => {
export const TableHead = ({
className = '',
children,
}: PropsWithChildren<{ className?: string }>) => (
<th scope="col" className={'px-6 py-3 ' + className}>
{children}
</th>
);

export const TableHeader = ({
className = '',
children,
}: PropsWithChildren<{ className?: string }>) => (
<thead
className={
'text-xs text-gray-700 uppercase dark:text-gray-400 ' + className
}
>
<TableRow>{children}</TableRow>
</thead>
);

export const TableRow = ({
className = '',
children,
}: PropsWithChildren<{ className?: string }>) => (
<tr className={'border-b border-gray-200 ' + className}>{children}</tr>
);

export const TableCell = ({
className = '',
children,
}: PropsWithChildren<{ className?: string }>) => (
<td className={'px-6 py-4' + className}>{children}</td>
);

export const TableBody = ({
className = '',
children,
}: PropsWithChildren<{ className?: string }>) => (
<tbody className={className}>{children}</tbody>
);

export const Table = ({
className = '',
children,
}: PropsWithChildren<{ className?: string }>) => {
return (
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead className="text-xs text-gray-700 uppercase dark:text-gray-400">
{props.headers?.length && (
<tr>
{props.headers.map((header, idx) => (
<>
<th
scope="col"
className={`px-6 py-3 ${
idx % 2 === 0 ? ' bg-gray-50 dark:bg-gray-800' : ''
}`}
>
{header}
</th>
</>
))}
</tr>
)}
</thead>
<tbody>
{props.data.map((row) => (
<tr
key={row[0].id}
className="border-b border-gray-200 dark:border-gray-700"
>
{row.map((col, colIdx) => (
<td
key={col.id}
className={`px-6 py-4 ${
colIdx % 2 === 0
? 'font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800'
: ''
}`}
>
{col.value}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<table
className={
'w-full text-sm text-left text-gray-500 dark:text-gray-400 ' + className
}
>
{children}
</table>
);
};

Table.Header = TableHeader;
Table.Head = TableHead;
Table.Row = TableRow;
Table.Cell = TableCell;
Table.Body = TableBody;
Table.Table = Table;

export default Table;
// key={col.id}
// className={`px-6 py-4 ${
// colIdx % 2 === 0
// ? 'font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800'
// : ''
// }`}
// >
16 changes: 1 addition & 15 deletions src/pages/Products/Products.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { ChangeEventHandler, useState } from 'react';
import {
LoaderFunction,
useLoaderData,
Outlet,
useParams,
Link,
useSearchParams,
} from 'react-router-dom';
import { LoaderFunction, useLoaderData, Outlet } from 'react-router-dom';

import { Search, Pagination } from '../../components';
import ApiClient from '../../app/ApiClient';
Expand All @@ -17,11 +10,9 @@ import { SearchResults } from './types';

export const ProductsPage = () => {
const onLoadData = useLoaderData() as SearchResults;
const [searchParams] = useSearchParams();
const [searchTerm, setSearchTerm] = useState(
localStorage.getItem('search-term') ?? ''
);
const { id } = useParams();
const { handleSearch, data, loading } = useData({
onLoadData,
});
Expand All @@ -40,11 +31,6 @@ export const ProductsPage = () => {
/>
<div className="flex gap-4">
<div className="grow">
{id && (
<Link to={`/products?${searchParams.toString()}`}>
<div className="overlay active" />
</Link>
)}
<ProductsContainer data={data?.products ?? []} loading={loading} />
</div>
<Outlet />
Expand Down
48 changes: 48 additions & 0 deletions src/pages/Products/components/ProductData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Table } from '../../../components';
import { Product } from '../types';

export const ProductTable = ({ product }: { product: Product }) => (
<Table>
<Table.Header>
<Table.Head className="bg-gray-50 dark:bg-gray-800 ">
Product Properties
</Table.Head>
<Table.Head>Property Values</Table.Head>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800">
Countries
</Table.Cell>
<Table.Cell>{product.countries.split(',').join(', ')}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800">
Brands
</Table.Cell>
<Table.Cell>{product.brands}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800">
Ingredients
</Table.Cell>
<Table.Cell>
{product.ingredients_text_en || product.ingredients_text}
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800">
Macro Elements
</Table.Cell>
<Table.Cell>
<ul>
<li>Prots - {product.nutriments.proteins_100g}</li>
<li>Carbs - {product.nutriments.carbohydrates_100g}</li>
<li>Fats - {product.nutriments.fat_100g}</li>
<li>Energy - {product.nutriments['energy-kcal_100g']}</li>
</ul>
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
);
Loading

0 comments on commit 31c56fd

Please sign in to comment.