Extract duplicate date range helpers to shared utility
- Created getDateRange() function in utils/date.ts - Replaced getBookableDates() and getDateRange() duplicates - Both booking and availability pages now use shared function - Function accepts minAdvanceDays and maxAdvanceDays as parameters
This commit is contained in:
parent
208278bddb
commit
5c396e62ec
3 changed files with 21 additions and 30 deletions
|
|
@ -8,26 +8,14 @@ import { Header } from "../../components/Header";
|
||||||
import { useRequireAuth } from "../../hooks/useRequireAuth";
|
import { useRequireAuth } from "../../hooks/useRequireAuth";
|
||||||
import { components } from "../../generated/api";
|
import { components } from "../../generated/api";
|
||||||
import constants from "../../../../shared/constants.json";
|
import constants from "../../../../shared/constants.json";
|
||||||
import { formatDate, formatDisplayDate } from "../../utils/date";
|
import { formatDate, formatDisplayDate, getDateRange } from "../../utils/date";
|
||||||
|
|
||||||
const { slotDurationMinutes, maxAdvanceDays } = constants.booking;
|
const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays } = constants.booking;
|
||||||
|
|
||||||
type AvailabilityDay = components["schemas"]["AvailabilityDay"];
|
type AvailabilityDay = components["schemas"]["AvailabilityDay"];
|
||||||
type AvailabilityResponse = components["schemas"]["AvailabilityResponse"];
|
type AvailabilityResponse = components["schemas"]["AvailabilityResponse"];
|
||||||
type TimeSlot = components["schemas"]["TimeSlot"];
|
type TimeSlot = components["schemas"]["TimeSlot"];
|
||||||
|
|
||||||
// Helper to get next N days starting from tomorrow
|
|
||||||
function getDateRange(): Date[] {
|
|
||||||
const dates: Date[] = [];
|
|
||||||
const today = new Date();
|
|
||||||
for (let i = 1; i <= maxAdvanceDays; i++) {
|
|
||||||
const d = new Date(today);
|
|
||||||
d.setDate(today.getDate() + i);
|
|
||||||
dates.push(d);
|
|
||||||
}
|
|
||||||
return dates;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate time options for dropdowns (15-min intervals)
|
// Generate time options for dropdowns (15-min intervals)
|
||||||
// Moved outside component since slotDurationMinutes is a constant
|
// Moved outside component since slotDurationMinutes is a constant
|
||||||
function generateTimeOptions(slotDurationMinutes: number): string[] {
|
function generateTimeOptions(slotDurationMinutes: number): string[] {
|
||||||
|
|
@ -64,10 +52,10 @@ export default function AdminAvailabilityPage() {
|
||||||
const [copyTargets, setCopyTargets] = useState<Set<string>>(new Set());
|
const [copyTargets, setCopyTargets] = useState<Set<string>>(new Set());
|
||||||
const [isCopying, setIsCopying] = useState(false);
|
const [isCopying, setIsCopying] = useState(false);
|
||||||
|
|
||||||
const dates = getDateRange();
|
const dates = getDateRange(minAdvanceDays, maxAdvanceDays);
|
||||||
|
|
||||||
const fetchAvailability = useCallback(async () => {
|
const fetchAvailability = useCallback(async () => {
|
||||||
const dateRange = getDateRange();
|
const dateRange = getDateRange(minAdvanceDays, maxAdvanceDays);
|
||||||
if (!dateRange.length) return;
|
if (!dateRange.length) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { Header } from "../components/Header";
|
||||||
import { useRequireAuth } from "../hooks/useRequireAuth";
|
import { useRequireAuth } from "../hooks/useRequireAuth";
|
||||||
import { components } from "../generated/api";
|
import { components } from "../generated/api";
|
||||||
import constants from "../../../shared/constants.json";
|
import constants from "../../../shared/constants.json";
|
||||||
import { formatDate, formatTime } from "../utils/date";
|
import { formatDate, formatTime, getDateRange } from "../utils/date";
|
||||||
|
|
||||||
const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays, noteMaxLength } = constants.booking;
|
const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays, noteMaxLength } = constants.booking;
|
||||||
|
|
||||||
|
|
@ -16,18 +16,6 @@ type BookableSlot = components["schemas"]["BookableSlot"];
|
||||||
type AvailableSlotsResponse = components["schemas"]["AvailableSlotsResponse"];
|
type AvailableSlotsResponse = components["schemas"]["AvailableSlotsResponse"];
|
||||||
type AppointmentResponse = components["schemas"]["AppointmentResponse"];
|
type AppointmentResponse = components["schemas"]["AppointmentResponse"];
|
||||||
|
|
||||||
// Get date range for booking (tomorrow to +30 days)
|
|
||||||
function getBookableDates(): Date[] {
|
|
||||||
const dates: Date[] = [];
|
|
||||||
const today = new Date();
|
|
||||||
for (let i = minAdvanceDays; i <= maxAdvanceDays; i++) {
|
|
||||||
const d = new Date(today);
|
|
||||||
d.setDate(today.getDate() + i);
|
|
||||||
dates.push(d);
|
|
||||||
}
|
|
||||||
return dates;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles: Record<string, React.CSSProperties> = {
|
const styles: Record<string, React.CSSProperties> = {
|
||||||
main: {
|
main: {
|
||||||
minHeight: "100vh",
|
minHeight: "100vh",
|
||||||
|
|
@ -244,7 +232,7 @@ export default function BookingPage() {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||||||
|
|
||||||
const dates = getBookableDates();
|
const dates = getDateRange(minAdvanceDays, maxAdvanceDays);
|
||||||
|
|
||||||
const fetchSlots = useCallback(async (date: Date) => {
|
const fetchSlots = useCallback(async (date: Date) => {
|
||||||
setIsLoadingSlots(true);
|
setIsLoadingSlots(true);
|
||||||
|
|
|
||||||
|
|
@ -46,3 +46,18 @@ export function formatDisplayDate(d: Date): string {
|
||||||
return d.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
|
return d.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get date range for booking/availability (from minAdvanceDays to maxAdvanceDays).
|
||||||
|
* Returns an array of Date objects starting from minAdvanceDays days from today.
|
||||||
|
*/
|
||||||
|
export function getDateRange(minAdvanceDays: number, maxAdvanceDays: number): Date[] {
|
||||||
|
const dates: Date[] = [];
|
||||||
|
const today = new Date();
|
||||||
|
for (let i = minAdvanceDays; i <= maxAdvanceDays; i++) {
|
||||||
|
const d = new Date(today);
|
||||||
|
d.setDate(today.getDate() + i);
|
||||||
|
dates.push(d);
|
||||||
|
}
|
||||||
|
return dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue