Skip to content

Commit

Permalink
Implement dummy Create card page (#6)
Browse files Browse the repository at this point in the history
* Rename add card to create card

* Implement PageTemplate.

* Use Page template in add-cards

* Add text inputs

* Add some dropdowns.

* Add some dropdowns.

* Add some dropdown fixes.

* Update main layout.

* Add some icon buttons.

* Adjust layout

* Adjust navigation.

* Finish create card page style.

* Adjust submit button name.

* Update plan
  • Loading branch information
lukasbicus authored Oct 24, 2024
1 parent e77c26e commit 1075128
Show file tree
Hide file tree
Showing 14 changed files with 340 additions and 55 deletions.
90 changes: 48 additions & 42 deletions app/(homescreens)/add-cards/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PredefinedCompanies, Routes } from '@/app/lib/shared';
import PageTemplate from '@/app/ui/page-template';
import { PrimaryHeader } from '@/app/ui/primary-header';
import {
IconGift,
Expand All @@ -10,48 +11,53 @@ import Link from 'next/link';

export default function Page() {
return (
<div className="h-full flex flex-col">
<PrimaryHeader
title="Add cards"
actions={
<Link href={Routes.ScanCard}>
<button className="btn btn-primary">
<IconPlus className="w-6 h-6" />
Add card
<PageTemplate
header={
<PrimaryHeader
title="Add cards"
actions={
<Link href={Routes.CreateCard}>
<button className="btn btn-primary">
<IconPlus className="w-6 h-6" />
Add card
</button>
</Link>
}
>
<>
<div className="form-control flex-1">
<label className="input input-bordered flex items-center gap-2 w-full">
<input
type="text"
className="grow w-full"
placeholder="Search"
/>
<IconSearch className="h-4 w-4 opacity-70"></IconSearch>
</label>
</div>
<button className="btn btn-circle btn-ghost">
<IconLayoutGrid className="w-6 h-6" />
</button>
</Link>
}
>
<>
<div className="form-control flex-1">
<label className="input input-bordered flex items-center gap-2 w-full">
<input type="text" className="grow w-full" placeholder="Search" />
<IconSearch className="h-4 w-4 opacity-70"></IconSearch>
</label>
</div>
<button className="btn btn-circle btn-ghost">
<IconLayoutGrid className="w-6 h-6" />
</button>
</>
</PrimaryHeader>
<main className="overflow-y-auto flex-1 bg-base-100">
<ul className="menu menu-lg rounded-box text-base-content">
{Object.values(PredefinedCompanies).map(company => (
<li key={company}>
<Link
href={{
pathname: Routes.ScanCard,
query: { predefinedCompany: company },
}}
prefetch={false}
>
<IconGift className="w-8 h-8" />
{company}
</Link>
</li>
))}
</ul>
</main>
</div>
</>
</PrimaryHeader>
}
>
<ul className="menu menu-lg rounded-box text-base-content">
{Object.values(PredefinedCompanies).map(company => (
<li key={company}>
<Link
href={{
pathname: Routes.CreateCard,
query: { predefinedCompany: company },
}}
prefetch={false}
>
<IconGift className="w-8 h-8" />
{company}
</Link>
</li>
))}
</ul>
</PageTemplate>
);
}
4 changes: 2 additions & 2 deletions app/(homescreens)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen">
<div className={styles.childrenHeight}>{children}</div>
<div
<footer
className={clsx(
`btm-nav btm-nav-lg text-base-content bg-base-200`,
styles.bottomBarNavHeight
)}
>
<BottomNavigationLinks />
</div>
</footer>
</div>
);
}
3 changes: 0 additions & 3 deletions app/add-card/page.tsx

This file was deleted.

66 changes: 66 additions & 0 deletions app/create-card/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { CardIcon, Colors, iconsMap, Routes } from '@/app/lib/shared';
import { DropdownField } from '@/app/ui/dropdown-field';
import PageTemplate from '@/app/ui/page-template';
import { SecondaryHeader } from '@/app/ui/secondary-header';
import { TextAreaField } from '@/app/ui/text-area-field';
import { TextField } from '@/app/ui/text-field';
import { IconCamera, IconPalette } from '@tabler/icons-react';
import Link from 'next/link';

export default function Page() {
return (
<PageTemplate
header={<SecondaryHeader title="Create a card" href={Routes.AddCards} />}
>
<form className="px-4 py-6 w-full h-full">
<div className="flex gap-4">
<TextField label="Card number" />
<Link
className="btn btn-primary btn-square mt-9"
href={Routes.ScanCard}
>
<IconCamera className="w-6 h-6" />
</Link>
</div>
<TextField label="Card name" />
<TextAreaField label="Note" />
<div className="flex gap-4">
<DropdownField
label="Background color"
dropdownClassName="dropdown-top"
value={Colors.Khaki}
options={Object.entries(Colors).map(([name, hex]) => ({
label: (
<div className="flex gap-2 items-center">
<div className="w-4 h-4" style={{ backgroundColor: hex }} />
<span>{name}</span>
</div>
),
value: hex,
}))}
/>
<button className="btn btn-primary btn-square mt-9">
<IconPalette className="w-6 h-6" />
</button>
</div>
<DropdownField
label="Icon"
dropdownClassName="dropdown-top"
value={CardIcon.Airlines}
options={Object.entries(iconsMap).map(([key, Icon]) => ({
label: (
<span>
<Icon className="w-6 h-6" />
</span>
),
value: key,
}))}
/>
<div className="h-32" />
<footer className="btm-nav btm-nav-md text-base-content px-4">
<button className="btn btn-primary w-full">Create card</button>
</footer>
</form>
</PageTemplate>
);
}
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<html lang="en" className="h-full">
<head>
<link
rel="icon"
Expand All @@ -50,7 +50,7 @@ export default function RootLayout({
<meta name="mobile-web-app-capable" content="yes" />
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-zinc-50`}
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-zinc-50 h-full max-h-screen`}
>
{children}
</body>
Expand Down
85 changes: 84 additions & 1 deletion app/lib/shared.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
import {
IconBarbell,
IconBed,
IconBooks,
IconCar,
IconChess,
IconCoffee,
IconDeviceLaptop,
IconFirstAidKit,
IconFlower,
IconGasStation,
IconPaint,
IconPaperBag,
IconPaperclip,
IconPaw,
IconPlane,
IconShoppingCart,
IconTheater,
IconTicket,
IconToolsKitchen2,
} from '@tabler/icons-react';

export enum Routes {
AddCards = '/add-cards',
MyCards = '/my-cards',
Settings = '/settings',
Offline = '/offline',
AddCard = '/add-card',
CreateCard = '/create-card',
ScanCard = '/scan-card',
}

Expand Down Expand Up @@ -34,3 +56,64 @@ export enum PredefinedCompanies {
TETA = 'Teta',
ZOOT = 'Zoot',
}

export enum CardIcon {
Grocery = 'Grocery',
Retail = 'Retail',
Pharmacy = 'Pharmacy',
Gas = 'Gas Station',
Restaurant = 'Restaurant',
Cafes = 'Cafés',
Accommodation = 'Accommodation',
Airlines = 'Airlines',
Car = 'Car Rental',
Culture = 'Culture',
Beauty = 'Beauty',
Books = 'Books',
Fitness = 'Fitness',
Electronic = 'Electronic',
Pet = 'Pet',
Hobby = 'Hobby',
Office = 'Office',
Gaming = 'Gaming',
Entertainment = 'Entertainment',
}
export const iconsMap = {
[CardIcon.Grocery]: IconShoppingCart,
[CardIcon.Retail]: IconPaperBag,
[CardIcon.Pharmacy]: IconFirstAidKit,
[CardIcon.Gas]: IconGasStation,
[CardIcon.Restaurant]: IconToolsKitchen2,
[CardIcon.Cafes]: IconCoffee,
[CardIcon.Accommodation]: IconBed,
[CardIcon.Airlines]: IconPlane,
[CardIcon.Car]: IconCar,
[CardIcon.Culture]: IconTheater,
[CardIcon.Beauty]: IconFlower,
[CardIcon.Books]: IconBooks,
[CardIcon.Fitness]: IconBarbell,
[CardIcon.Electronic]: IconDeviceLaptop,
[CardIcon.Pet]: IconPaw,
[CardIcon.Hobby]: IconPaint,
[CardIcon.Office]: IconPaperclip,
[CardIcon.Gaming]: IconChess,
[CardIcon.Entertainment]: IconTicket,
};

export enum Colors {
SkyBlue = '#87CEEB',
Coral = '#FF7F50',
LightGreen = '#90EE90',
SandyBrown = '#F4A460',
Plum = '#DDA0DD',
CadetBlue = '#5F9EA0',
Salmon = '#FA8072',
Khaki = '#F0E68C',
SlateGray = '#708090',
Thistle = '#D8BFD8',
LightCoral = '#F08080',
PaleTurquoise = '#AFEEEE',
Tan = '#D2B48C',
LightSlateGray = '#778899',
Burlywood = '#DEB887',
}
49 changes: 49 additions & 0 deletions app/ui/dropdown-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import clsx from 'clsx';

export type Option<T> = {
label: string | React.ReactNode;
value: T;
};

export function DropdownField<T = string>({
label,
className,
dropdownClassName,
options,
value,
}: {
label: string;
className?: string;
dropdownClassName?: string;
options: Option<T>[];
value?: T;
}) {
const currentOption = options.find(option => option.value === value);

return (
<label className={clsx('form-control w-full', className)}>
<div className="label">
<span className="label-text">{label}</span>
</div>
<div className={clsx('dropdown dropdown-end', dropdownClassName)}>
<div className="input input-bordered w-full flex items-center">
{currentOption ? (
<div tabIndex={0} role="button" className="w-full">
{currentOption.label}
</div>
) : (
<input tabIndex={0} type="text" role="button" className="w-full" />
)}
</div>
<ul
tabIndex={0}
className="dropdown-content menu bg-base-100 rounded-box z-[1] w-full p-2 shadow max-h-96 overflow-auto"
>
{options.map(option => (
<li key={String(option.value)}>{option.label}</li>
))}
</ul>
</div>
</label>
);
}
17 changes: 17 additions & 0 deletions app/ui/page-template.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default function PageTemplate({
header,
children,
footer,
}: {
header: React.ReactNode;
footer?: React.ReactNode;
children: React.ReactNode;
}) {
return (
<div className="h-full flex flex-col text-base-content">
{header}
<main className="overflow-y-auto flex-1 bg-base-100">{children}</main>
{footer}
</div>
);
}
4 changes: 2 additions & 2 deletions app/ui/primary-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function PrimaryHeader({
}) {
return (
<header>
<div className="navbar bg-base-200 text-base-content">
<div className="navbar bg-base-200">
<div className="navbar-start">
<Image
src="/logo.svg"
Expand All @@ -20,7 +20,7 @@ export function PrimaryHeader({
width={24}
height={24}
/>
<h1 className="btn btn-ghost text-lg">{title}</h1>
<h1 className="text-lg pl-4">{title}</h1>
</div>
{actions && <div className="navbar-end">{actions}</div>}
</div>
Expand Down
Loading

0 comments on commit 1075128

Please sign in to comment.