did more stuff
This commit is contained in:
parent
91b947c608
commit
cb00826b16
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user