Skip to content

Commit

Permalink
Merge branch 'main' into 28-feat-set-up-database-and-trcp
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbrusegard committed Aug 29, 2024
2 parents e8f618b + 9974673 commit 828e8bd
Show file tree
Hide file tree
Showing 17 changed files with 1,101 additions and 1 deletion.
27 changes: 27 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"navigationMenu": "Navigation menu",
"news": "News",
"events": "Events",
"storage": "Storage",
"about": "About",
"changeLocale": "Change language",
"toggleTheme": "Toggle theme",
Expand Down Expand Up @@ -48,5 +49,31 @@
"newArticle": "New article",
"readTime": "{count, plural, =0 {less than a minute} one {# minute} other {# minutes}} read",
"views": "Views"
},
"storage": {
"title": "Storage",
"card": {
"quantityInfo": "{quantity} units",
"addToCart": "Add to cart"
},
"select": {
"filters": "Filters",
"defaultPlaceholder": "Sort results",
"popularity": "Popularity",
"sortDescending": "Inventory (descending)",
"sortAscending": "Inventory (ascending)",
"name": "Name (in alphabetical order)"
},
"combobox": {
"defaultDescription": "Choose category...",
"defaultPlaceholder": "Search category...",
"cables": "Cables",
"sensors": "Sensors",
"peripherals": "PC peripherals",
"miniPC": "Mini PC"
},
"tooltips": {
"viewShoppingCart": "View shopping cart"
}
}
}
27 changes: 27 additions & 0 deletions messages/no.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"navigationMenu": "Navigasjonsmeny",
"news": "Nyheter",
"events": "Hendelser",
"storage": "Lager",
"about": "Om oss",
"changeLocale": "Bytt språk",
"toggleTheme": "Bytt tema",
Expand Down Expand Up @@ -48,5 +49,31 @@
"newArticle": "Ny artikkel",
"readTime": "{count, plural, =0 {mindre enn ett minutt} one {# minutt} other {# minutter}} lesing",
"views": "Visninger"
},
"storage": {
"title": "Lager",
"card": {
"quantityInfo": "{quantity} stk.",
"addToCart": "Legg i handlekurven"
},
"select": {
"filters": "Filtre",
"defaultPlaceholder": "Sorter resultater",
"popularity": "Popularitet",
"sortDescending": "Lagerbeholdning (synkende)",
"sortAscending": "Lagerbeholdning (stigende)",
"name": "Navn (alfabetisk)"
},
"combobox": {
"defaultDescription": "Velg kategori...",
"defaultPlaceholder": "Søk etter kategori...",
"cables": "Kabler",
"sensors": "Sensorer",
"peripherals": "PC-tilbehør",
"miniPC": "Mini-PC"
},
"tooltips": {
"viewShoppingCart": "Vis handlekurv"
}
}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.1",
Expand All @@ -33,6 +35,7 @@
"@trpc/react-query": "^10.45.2",
"@trpc/server": "^10.45.2",
"autoprefixer": "^10.4.19",
"cmdk": "1.0.0",
"country-flag-icons": "^1.5.12",
"cva": "^1.0.0-beta.1",
"drizzle-orm": "^0.33.0",
Expand All @@ -49,7 +52,7 @@
"reading-time": "^1.5.0",
"server-only": "^0.0.1",
"sharp": "^0.33.4",
"tailwind-merge": "^2.3.0",
"tailwind-merge": "^2.5.2",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
Binary file added public/unknown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions src/app/[locale]/(default)/storage/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useTranslations } from 'next-intl';

import { Button } from '@/components/ui/Button';

import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/Tooltip';
import { ShoppingCart } from 'lucide-react';

export default function StorageLayout({
children,
}: {
children: React.ReactNode;
}) {
const t = useTranslations('storage');

return (
<>
<div className='relative'>
<h1 className='my-4 md:text-center'>{t('title')}</h1>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button className='absolute right-0 bottom-0 md:right-5'>
<ShoppingCart />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>{t('tooltips.viewShoppingCart')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
{children}
</>
);
}
24 changes: 24 additions & 0 deletions src/app/[locale]/(default)/storage/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SkeletonCard } from '@/components/storage/SkeletonCard';
import { Skeleton } from '@/components/ui/Skeleton';

export default function StorageSkeleton() {
return (
<>
<div className='my-4 flex flex-col justify-center gap-2 lg:flex-row'>
<Skeleton className='h-10 w-full' />
<Skeleton className='h-10 w-full lg:w-[250px]' />
<Skeleton className='h-10 w-full lg:w-[250px]' />
</div>
<div className='grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'>
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
</div>
</>
);
}
158 changes: 158 additions & 0 deletions src/app/[locale]/(default)/storage/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { items } from '@/mock-data/items';
import { useTranslations } from 'next-intl';
import { getTranslations, unstable_setRequestLocale } from 'next-intl/server';
import Image from 'next/image';
import { createSearchParamsCache, parseAsInteger } from 'nuqs/parsers';

import { PaginationCarousel } from '@/components/layout/PaginationCarousel';
import { Button } from '@/components/ui/Button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/Card';
import { Combobox } from '@/components/ui/Combobox';
import { SearchBar } from '@/components/ui/SearchBar';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/Select';

export async function generateMetadata({
params: { locale },
}: {
params: { locale: string };
}) {
const t = await getTranslations({ locale, namespace: 'layout' });

return {
title: t('storage'),
};
}

export default function StoragePage({
params: { locale },
searchParams,
}: {
params: { locale: string };
searchParams: Record<string, string | string[] | undefined>;
}) {
unstable_setRequestLocale(locale);
const t = useTranslations('storage');
const t_ui = useTranslations('ui');

const itemsPerPage = 12;

const searchParamsCache = createSearchParamsCache({
[t_ui('page')]: parseAsInteger.withDefault(1),
});

const { [t_ui('page')]: page = 1 } = searchParamsCache.parse(searchParams);

// TODO: Implement filters and category selection
const categories = [
{
value: 'cables',
label: t('combobox.cables'),
},
{
value: 'sensors',
label: t('combobox.sensors'),
},
{
value: 'peripherals',
label: t('combobox.peripherals'),
},
{
value: 'miniPC',
label: t('combobox.miniPC'),
},
];

const filters = [
'select.popularity',
'select.sortDescending',
'select.sortAscending',
'select.name',
] as const;

return (
<>
<div className='my-4 flex flex-col justify-center gap-2 lg:flex-row'>
<SearchBar className='lg:max-w-2xl' />
<Select>
<SelectTrigger className='w-full lg:w-[250px]'>
<SelectValue placeholder={t('select.defaultPlaceholder')} />
</SelectTrigger>
<SelectContent>
{filters.map((filter) => (
<SelectItem key={filter} value={filter}>
{t(filter)}
</SelectItem>
))}
</SelectContent>
</Select>

<Combobox
choices={categories}
defaultDescription={t('combobox.defaultDescription')}
defaultPlaceholder={t('combobox.defaultPlaceholder')}
buttonClassName='w-full lg:w-[250px]'
contentClassName='w-full lg:w-[200px]'
/>
</div>
<div className='grid grid-cols-1 xs:grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-4'>
{items
.slice((page - 1) * itemsPerPage, page * itemsPerPage)
.map((item) => (
<Card
key={item.name}
className='group text-center duration-200 hover:box-border hover:border-primary'
>
<CardHeader>
<div className='inline-block overflow-hidden'>
<Image
src='/unknown.png'
width={192}
height={192}
alt={`Photo of ${item.name}`}
className='mx-auto rounded-md duration-200 group-hover:scale-105'
/>
</div>
<CardTitle className='mt-2 truncate'>{item.name}</CardTitle>
<CardDescription className='flex flex-col gap-1'>
<span>{item.location}</span>
</CardDescription>
</CardHeader>
<CardFooter className='justify-center gap-2'>
<span className='text-sm'>
{t('card.quantityInfo', { quantity: item.quantity })}
</span>
<Button className='whitespace-break-spaces'>
{t('card.addToCart')}
</Button>
</CardFooter>
</Card>
))}
</div>
<PaginationCarousel
className='my-6'
totalPages={Math.ceil(items.length / itemsPerPage)}
t={{
goToPreviousPage: t_ui('goToPreviousPage'),
previous: t_ui('previous'),
morePages: t_ui('morePages'),
goToNextPage: t_ui('goToNextPage'),
next: t_ui('next'),
page: t_ui('page'),
}}
/>
</>
);
}
17 changes: 17 additions & 0 deletions src/components/storage/SkeletonCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Skeleton } from '@/components/ui/Skeleton';

export function SkeletonCard() {
return (
<div className='flex h-[350px] flex-col gap-5'>
<div className='flex flex-col items-center justify-center gap-2'>
<Skeleton className='h-[192px] w-[192px] rounded-lg' />
<Skeleton className='h-[24px] w-[120px] rounded-full' />
<Skeleton className='h-[14px] w-[70px] rounded-full' />
</div>
<div className='flex items-center justify-center gap-2'>
<Skeleton className='h-[14px] w-[70px] rounded-full' />
<Skeleton className='h-8 w-[100px] rounded-lg' />
</div>
</div>
);
}
Loading

0 comments on commit 828e8bd

Please sign in to comment.