did more stuff

This commit is contained in:
Gabriel Brown 2024-09-01 19:48:10 -05:00
parent 91b947c608
commit cb00826b16
3 changed files with 123 additions and 12 deletions

View File

@ -1,18 +1,73 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { Calendar } from "~/components/ui/BillTrackerCalendar" import { Calendar } from "~/components/ui/BillTrackerCalendar"
import { Button } from "~/components/ui/button"
export default function BillTrackerCalendar() { export default function BillTrackerCalendar() {
const [date, setDate] = React.useState<Date | undefined>(new Date()) const [selectedDate, setSelectedDate] = React.useState<Date | undefined>(undefined)
const [isOpen, setIsOpen] = React.useState(false)
const calendarRef = React.useRef<HTMLDivElement>(null)
const popoverRef = React.useRef<HTMLDivElement>(null)
const handleSelect = (date: Date | undefined) => {
if (date) {
if (selectedDate && date.getTime() === selectedDate.getTime())
setIsOpen(!isOpen)
else {
setSelectedDate(date)
setIsOpen(true)
}
} else
setIsOpen(false)
}
React.useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
calendarRef.current &&
popoverRef.current &&
!calendarRef.current.contains(event.target as Node) &&
!popoverRef.current.contains(event.target as Node)
) {
setIsOpen(false)
}
}
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [])
return ( return (
<div className="m-auto p-2"> <div className="m-auto p-2 relative" ref={calendarRef}>
<Calendar <Calendar
mode="single" mode="single"
selected={date} selected={selectedDate}
onSelect={setDate} onSelect={handleSelect}
className="rounded-md border m-auto" className="rounded-md border m-auto"
/> />
{isOpen && selectedDate && (
<div
ref={popoverRef}
className="absolute top-full left-1/2 transform -translate-x-1/2 border rounded-lg shadow-lg px-4 pb-4 w-80"
>
<div className="grid gap-4">
<div className="space-y-2">
<div className="flex flex-row w-full">
<h3 className="font-medium leading-none text-center mx-auto mt-2 py-2 md:text-xl">
{selectedDate.toDateString()}
</h3>
<button className="justify-self-end ml-auto bg-none text-primary text-m md:text-xl"
onClick={() => setIsOpen(false)}
>
x
</button>
</div>
<p>Add your events or bills due here.</p>
</div>
</div>
</div>
)}
</div> </div>
) )
} }

View File

@ -3,7 +3,6 @@
import * as React from "react" import * as React from "react"
import { ChevronLeft, ChevronRight } from "lucide-react" import { ChevronLeft, ChevronRight } from "lucide-react"
import { DayPicker } from "react-day-picker" import { DayPicker } from "react-day-picker"
import { cn } from "~/lib/utils" import { cn } from "~/lib/utils"
import { buttonVariants } from "~/components/ui/button" import { buttonVariants } from "~/components/ui/button"

View File

@ -16,15 +16,18 @@ const connectionString = process.env.DATABASE_URL ?? "";
const pool = postgres(connectionString, { max: 1 }) const pool = postgres(connectionString, { max: 1 })
export const db = drizzle(pool) export const db = drizzle(pool)
export const frequencyEnum = pgEnum("frequency", ["Monthly", "Bi-weekly", "Weekly"]) export const frequencyEnum = pgEnum("frequency", ["Monthly", "Bi-weekly", "Weekly"]);
export const workOrderStatusEnum = pgEnum("workOrderStatus", ["Pending", "Open", "Closed"]) export const workOrderStatusEnum = pgEnum("workOrderStatus", ["Pending", "Open", "Closed"]);
export const paymentTypeEnum = pgEnum("paymentType", ["Security Deposit", "Rent", "Late Fee", "Other"]) export const paymentTypeEnum = pgEnum("paymentType", ["Security Deposit", "Rent", "Late Fee", "Other"]);
export const paymentStatusEnum = pgEnum("paymentStatus", ["Pending", "Complete", "Late", "Refunded"]) export const paymentStatusEnum = pgEnum("paymentStatus", ["Pending", "Complete", "Late", "Refunded"]);
export const preferredDaysofWeekEnum = pgEnum("preferredDaysofWeek", export const preferredDaysofWeekEnum = pgEnum("preferredDaysofWeek",
["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]) ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
);
export const propertyTypeEnum = pgEnum("propertyType", ["Apartment", "Condominium", export const propertyTypeEnum = pgEnum("propertyType", ["Apartment", "Condominium",
"Mobile Home", "Multi-Unit Home", "Single-Family Residence", "Townhouse"]) "Mobile Home", "Multi-Unit Home", "Single-Family Residence", "Townhouse"]
export const workOrderPriorityEnum = pgEnum("workOrderPriority", ["Low", "High"]) );
export const workOrderPriorityEnum = pgEnum("workOrderPriority", ["Low", "High"]
);
export const workOrderTypeEnum = pgEnum("workOrderType", export const workOrderTypeEnum = pgEnum("workOrderType",
["Appliance Repair", "Carbon Monoxide Detector Installation", "Ceiling Fan Repair", ["Appliance Repair", "Carbon Monoxide Detector Installation", "Ceiling Fan Repair",
"Carpentry Repair", "Door Installation/Repair", "Drywall Installation/Repair", "Carpentry Repair", "Door Installation/Repair", "Drywall Installation/Repair",
@ -35,6 +38,19 @@ export const workOrderTypeEnum = pgEnum("workOrderType",
"Tile Flooring", "Tree Trimming/Cutting", "Water Treatment", "Well/Water Testing", "Tile Flooring", "Tree Trimming/Cutting", "Water Treatment", "Well/Water Testing",
"Window Repair/Installation"] "Window Repair/Installation"]
); );
export const billStatusEnum = pgEnum("billStatus",
["Awaiting Payment", "Paid", "Scheduled", "Late", "Refunded"]
);
export const billTypeEnum = pgEnum("billType",
["Rent", "Power", "Internet", "Gas", "Water", "Phone Bill", "Cable",
"Security Deposit", "Other"]
);
export const billPaymentTypeEnum = pgEnum("billPaymentType",
["Paid Online", "Zelle", "Cash", "Cash App", "Apple Pay"]
);
export const billRecurrenceEnum = pgEnum("billRecurrence",
["Monthly", "Bi-weekly", "Weekly", "Annually"]
);
export const users = pgTable( export const users = pgTable(
"user", "user",
@ -210,3 +226,44 @@ export const emergencyContacts = pgTable(
email: text("email"), email: text("email"),
} }
) )
export const bills = pgTable(
"bill",
{
id: text("id").primaryKey(),
billType: billTypeEnum("billType").notNull(),
billDescription: text("billDescription"),
createdBy: text("createdBy").notNull().references(() => users.id, { onDelete: "cascade" }),
createdAt: timestamp("createdAt").notNull().defaultNow(),
dueDate: timestamp("dueDate").notNull(),
amount: numeric("amount").notNull(),
currency: text("currency").notNull().default("USD"),
recurrence: billRecurrenceEnum("recurrence"),
attachmentUrl: text("attachmentUrl"),
}
)
export const billsSplitBetween = pgTable(
"billSplitBetween",
{
id: text("id").primaryKey(),
billID: text("billID").notNull().references(() => bills.id, { onDelete: "cascade" }),
userID: text("userID").notNull().references(() => users.id, { onDelete: "cascade" }),
amount: numeric("amount").notNull(),
status: billStatusEnum("status").notNull(),
paymentType: billPaymentTypeEnum("paymentType"),
paidAt: timestamp("paidAt"),
attachmentUrl: text("attachmentUrl"),
}
)
export const billReminders = pgTable(
"billReminders",
{
id: text("id").primaryKey(),
billID: text("billID").notNull().references(() => bills.id, { onDelete: "cascade" }),
userID: text("userID").notNull().references(() => users.id, { onDelete: "cascade" }),
reminderDate: timestamp("reminderDate").notNull(),
reminderSent: boolean("reminderSent").notNull().default(false),
}
)