work on bill tracker page. add calendar.
This commit is contained in:
parent
52b8a4c1cb
commit
91b947c608
@ -31,6 +31,7 @@
|
|||||||
"@types/jsonwebtoken": "^9.0.6",
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"date-fns": "^3.6.0",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"drizzle-orm": "^0.30.10",
|
"drizzle-orm": "^0.30.10",
|
||||||
"geist": "^1.3.1",
|
"geist": "^1.3.1",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
"postgres": "^3.4.4",
|
"postgres": "^3.4.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"react-day-picker": "8.10.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.52.2",
|
"react-hook-form": "^7.52.2",
|
||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
|
@ -50,6 +50,9 @@ importers:
|
|||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
|
date-fns:
|
||||||
|
specifier: ^3.6.0
|
||||||
|
version: 3.6.0
|
||||||
dotenv:
|
dotenv:
|
||||||
specifier: ^16.4.5
|
specifier: ^16.4.5
|
||||||
version: 16.4.5
|
version: 16.4.5
|
||||||
@ -80,6 +83,9 @@ importers:
|
|||||||
react:
|
react:
|
||||||
specifier: ^18.3.1
|
specifier: ^18.3.1
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
|
react-day-picker:
|
||||||
|
specifier: 8.10.1
|
||||||
|
version: 8.10.1(date-fns@3.6.0)(react@18.3.1)
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^18.3.1
|
specifier: ^18.3.1
|
||||||
version: 18.3.1(react@18.3.1)
|
version: 18.3.1(react@18.3.1)
|
||||||
@ -1521,6 +1527,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
|
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
date-fns@3.6.0:
|
||||||
|
resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
|
||||||
|
|
||||||
debug@3.2.7:
|
debug@3.2.7:
|
||||||
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2703,6 +2712,12 @@ packages:
|
|||||||
queue-microtask@1.2.3:
|
queue-microtask@1.2.3:
|
||||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||||
|
|
||||||
|
react-day-picker@8.10.1:
|
||||||
|
resolution: {integrity: sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==}
|
||||||
|
peerDependencies:
|
||||||
|
date-fns: ^2.28.0 || ^3.0.0
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
|
||||||
react-dom@18.3.1:
|
react-dom@18.3.1:
|
||||||
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
|
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -4333,6 +4348,8 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
is-data-view: 1.0.1
|
is-data-view: 1.0.1
|
||||||
|
|
||||||
|
date-fns@3.6.0: {}
|
||||||
|
|
||||||
debug@3.2.7:
|
debug@3.2.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
@ -5659,6 +5676,11 @@ snapshots:
|
|||||||
|
|
||||||
queue-microtask@1.2.3: {}
|
queue-microtask@1.2.3: {}
|
||||||
|
|
||||||
|
react-day-picker@8.10.1(date-fns@3.6.0)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
date-fns: 3.6.0
|
||||||
|
react: 18.3.1
|
||||||
|
|
||||||
react-dom@18.3.1(react@18.3.1):
|
react-dom@18.3.1(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
|
19
src/app/billtracker/page.tsx
Normal file
19
src/app/billtracker/page.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
"use server"
|
||||||
|
import { auth } from "~/auth"
|
||||||
|
import BreadCrumbBillTracker from "~/components/home/breadcrumb/BreadCrumbBillTracker"
|
||||||
|
import BillTrackerCalendar from "~/components/billtracker/BillTrackerCalendar"
|
||||||
|
|
||||||
|
export default async function HomePage() {
|
||||||
|
const session = await auth()
|
||||||
|
if (!session?.user) return <></>
|
||||||
|
return (
|
||||||
|
<div className="w-2/3 flex flex-col p-6">
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="">
|
||||||
|
<BreadCrumbBillTracker />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
< BillTrackerCalendar />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -79,7 +79,7 @@ export default async function RootLayout({
|
|||||||
< First_Sign_In_Form users_name={users_name} users_email={users_email} />
|
< First_Sign_In_Form users_name={users_name} users_email={users_email} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row p-4">
|
<div className="flex flex-row p-4">
|
||||||
<div className="w-1/4 p-4">
|
<div className="w-1/6 md:w-1/4 p-4">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Hero />
|
<Hero />
|
||||||
<Nav_Bar />
|
<Nav_Bar />
|
||||||
|
18
src/components/billtracker/BillTrackerCalendar.tsx
Normal file
18
src/components/billtracker/BillTrackerCalendar.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
"use client"
|
||||||
|
import * as React from "react"
|
||||||
|
import { Calendar } from "~/components/ui/BillTrackerCalendar"
|
||||||
|
|
||||||
|
export default function BillTrackerCalendar() {
|
||||||
|
const [date, setDate] = React.useState<Date | undefined>(new Date())
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-auto p-2">
|
||||||
|
<Calendar
|
||||||
|
mode="single"
|
||||||
|
selected={date}
|
||||||
|
onSelect={setDate}
|
||||||
|
className="rounded-md border m-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -9,12 +9,12 @@ const fontSans = FontSans({
|
|||||||
export default function Hero() {
|
export default function Hero() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col justify-start items-start">
|
<div className="flex flex-col justify-start items-start">
|
||||||
<h1 className={cn("text-6xl font-bold text-center font-sans antialiased",
|
<h1 className={cn("text-4xl md:text-5xl lg:text-6xl font-bold text-center font-sans antialiased",
|
||||||
fontSans.variable)}
|
fontSans.variable)}
|
||||||
>
|
>
|
||||||
TENANT
|
TENANT
|
||||||
</h1>
|
</h1>
|
||||||
<h1 className={cn("text-6xl font-bold text-center font-sans antialiased",
|
<h1 className={cn("text-4xl md:text-5xl lg:text-6xl font-bold text-center font-sans antialiased",
|
||||||
fontSans.variable)}
|
fontSans.variable)}
|
||||||
>
|
>
|
||||||
PORTAL
|
PORTAL
|
||||||
|
@ -14,9 +14,9 @@ const fontSans = FontSans({
|
|||||||
export default function Nav_Bar() {
|
export default function Nav_Bar() {
|
||||||
return (
|
return (
|
||||||
<div className={cn("flex flex-col justify-start items-start " +
|
<div className={cn("flex flex-col justify-start items-start " +
|
||||||
"py-6 text-2xl font-semibold font-sans antialiased", fontSans.variable)}
|
"py-6 text-lg md:text-xl lg:text-2xl font-semibold font-sans antialiased", fontSans.variable)}
|
||||||
>
|
>
|
||||||
<Card className="p-4">
|
<Card className="md:p-4">
|
||||||
<CardContent className="py-4">
|
<CardContent className="py-4">
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
Dashboard
|
Dashboard
|
||||||
@ -58,7 +58,7 @@ export default function Nav_Bar() {
|
|||||||
</Link>
|
</Link>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardContent className="pt-4">
|
<CardContent className="pt-4">
|
||||||
<Link href="/">
|
<Link href="/billtracker">
|
||||||
Bill Tracker
|
Bill Tracker
|
||||||
</Link>
|
</Link>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
31
src/components/home/breadcrumb/BreadCrumbBillTracker.tsx
Normal file
31
src/components/home/breadcrumb/BreadCrumbBillTracker.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbSeparator,
|
||||||
|
} from "~/components/ui/breadcrumb"
|
||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
|
export default function Breadcrumb_Home() {
|
||||||
|
return (
|
||||||
|
<Breadcrumb className="w-full m-auto flex flex-row justify-center items-center">
|
||||||
|
<BreadcrumbList>
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<Link href="/">
|
||||||
|
<h1 className="text-xl pl-20 pt-4 lg:text-3xl lg:pl-0 lg:pt-0 font-bold text-center font-sans antialiased">
|
||||||
|
Dashboard
|
||||||
|
</h1>
|
||||||
|
</Link>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbSeparator className="pt-4 lg:pt-0"/>
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<Link href="/billtracker">
|
||||||
|
<h1 className="text-xl pt-4 lg:text-3xl lg:pt-0 font-bold text-center font-sans antialiased">
|
||||||
|
Bill Tracker
|
||||||
|
</h1>
|
||||||
|
</Link>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
</BreadcrumbList>
|
||||||
|
</Breadcrumb>
|
||||||
|
);
|
||||||
|
};
|
66
src/components/ui/BillTrackerCalendar.tsx
Normal file
66
src/components/ui/BillTrackerCalendar.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import { ChevronLeft, ChevronRight } from "lucide-react"
|
||||||
|
import { DayPicker } from "react-day-picker"
|
||||||
|
|
||||||
|
import { cn } from "~/lib/utils"
|
||||||
|
import { buttonVariants } from "~/components/ui/button"
|
||||||
|
|
||||||
|
export type CalendarProps = React.ComponentProps<typeof DayPicker>
|
||||||
|
|
||||||
|
function Calendar({
|
||||||
|
className,
|
||||||
|
classNames,
|
||||||
|
showOutsideDays = true,
|
||||||
|
...props
|
||||||
|
}: CalendarProps) {
|
||||||
|
return (
|
||||||
|
<DayPicker
|
||||||
|
showOutsideDays={showOutsideDays}
|
||||||
|
className={cn("p-3", className)}
|
||||||
|
classNames={{
|
||||||
|
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
|
||||||
|
month: "space-y-4",
|
||||||
|
caption: "flex justify-center pt-1 relative items-center",
|
||||||
|
caption_label: "text-2xl lg:text-4xl font-semibold p-2",
|
||||||
|
nav: "space-x-1 flex items-center",
|
||||||
|
nav_button: cn(
|
||||||
|
buttonVariants({ variant: "outline" }),
|
||||||
|
"h-12 w-12 lg:h-18 lg:w-18 bg-transparent p-0 opacity-50 hover:opacity-100"
|
||||||
|
),
|
||||||
|
nav_button_previous: "absolute left-1",
|
||||||
|
nav_button_next: "absolute right-1",
|
||||||
|
table: "w-full border-collapse space-y-1",
|
||||||
|
head_row: "flex",
|
||||||
|
head_cell:
|
||||||
|
"text-muted-foreground rounded-md w-16 lg:w-24 font-normal text-[1.2rem]",
|
||||||
|
row: "flex w-full mt-2",
|
||||||
|
cell: "h-16 w-16 lg:h-24 lg:w-24 text-center text-sm lg:text-xl p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
|
||||||
|
day: cn(
|
||||||
|
buttonVariants({ variant: "ghost" }),
|
||||||
|
"h-16 w-16 lg:h-24 lg:w-24 p-0 font-normal aria-selected:opacity-100"
|
||||||
|
),
|
||||||
|
day_range_end: "day-range-end",
|
||||||
|
day_selected:
|
||||||
|
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
|
||||||
|
day_today: "bg-accent text-accent-foreground",
|
||||||
|
day_outside:
|
||||||
|
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
|
||||||
|
day_disabled: "text-muted-foreground opacity-50",
|
||||||
|
day_range_middle:
|
||||||
|
"aria-selected:bg-accent aria-selected:text-accent-foreground",
|
||||||
|
day_hidden: "invisible",
|
||||||
|
...classNames,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
IconLeft: ({ ...props }) => <ChevronLeft className="h-6 w-6" />,
|
||||||
|
IconRight: ({ ...props }) => <ChevronRight className="h-6 w-6" />,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Calendar.displayName = "Calendar"
|
||||||
|
|
||||||
|
export { Calendar }
|
Loading…
Reference in New Issue
Block a user