mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
RV/Boat Lots: waitlist size + more vehicle types
- Waitlist now captures a free-form Size (requested_size column) in place of the type field in the internal form/table. - Lot type selector (add + bulk edit) expanded to RV, Boat, Travel Trailer, Fifth Wheel, Camper, Car, Truck, Trailer, Other. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -32,12 +32,25 @@ type Rental = {
|
||||
type WaitlistEntry = {
|
||||
id: string; association_id: string; position: number;
|
||||
requester_name: string; requester_email: string | null; requester_phone: string | null;
|
||||
unit_address: string | null; requested_lot_type: string;
|
||||
unit_address: string | null; requested_lot_type: string; requested_size: string | null;
|
||||
vehicle_description: string | null; notes: string | null;
|
||||
status: string; source: string; joined_at: string;
|
||||
fulfilled_at: string | null; fulfilled_lot_number: string | null;
|
||||
};
|
||||
|
||||
const VEHICLE_TYPES = [
|
||||
{ value: "rv", label: "RV" },
|
||||
{ value: "boat", label: "Boat" },
|
||||
{ value: "travel_trailer", label: "Travel Trailer" },
|
||||
{ value: "fifth_wheel", label: "Fifth Wheel" },
|
||||
{ value: "camper", label: "Camper" },
|
||||
{ value: "car", label: "Car" },
|
||||
{ value: "truck", label: "Truck" },
|
||||
{ value: "trailer", label: "Trailer" },
|
||||
{ value: "other", label: "Other" },
|
||||
];
|
||||
const vehicleTypeLabel = (v: string) => VEHICLE_TYPES.find(t => t.value === v)?.label || v;
|
||||
|
||||
export default function RVBoatLotsPage() {
|
||||
const associationCtx = useAssociation() as any;
|
||||
const ctxAssociation = associationCtx?.selectedAssociation ?? null;
|
||||
@@ -78,7 +91,7 @@ export default function RVBoatLotsPage() {
|
||||
});
|
||||
const [waitlistForm, setWaitlistForm] = useState({
|
||||
requester_name: "", requester_email: "", requester_phone: "",
|
||||
unit_address: "", requested_lot_type: "either", vehicle_description: "", notes: ""
|
||||
unit_address: "", requested_lot_type: "either", requested_size: "", vehicle_description: "", notes: ""
|
||||
});
|
||||
|
||||
// batch edit state
|
||||
@@ -318,6 +331,7 @@ export default function RVBoatLotsPage() {
|
||||
requester_phone: waitlistForm.requester_phone || null,
|
||||
unit_address: waitlistForm.unit_address || null,
|
||||
requested_lot_type: waitlistForm.requested_lot_type,
|
||||
requested_size: waitlistForm.requested_size || null,
|
||||
vehicle_description: waitlistForm.vehicle_description || null,
|
||||
notes: waitlistForm.notes || null,
|
||||
source: "manual",
|
||||
@@ -327,7 +341,7 @@ export default function RVBoatLotsPage() {
|
||||
if (error) { toast.error(error.message); return; }
|
||||
toast.success("Added to waitlist");
|
||||
setWaitlistDialogOpen(false);
|
||||
setWaitlistForm({ requester_name: "", requester_email: "", requester_phone: "", unit_address: "", requested_lot_type: "either", vehicle_description: "", notes: "" });
|
||||
setWaitlistForm({ requester_name: "", requester_email: "", requester_phone: "", unit_address: "", requested_lot_type: "either", requested_size: "", vehicle_description: "", notes: "" });
|
||||
load();
|
||||
};
|
||||
|
||||
@@ -435,17 +449,7 @@ export default function RVBoatLotsPage() {
|
||||
<div><Label>Phone</Label><Input value={waitlistForm.requester_phone} onChange={e => setWaitlistForm({ ...waitlistForm, requester_phone: e.target.value })} /></div>
|
||||
</div>
|
||||
<div><Label>Unit / Address</Label><Input value={waitlistForm.unit_address} onChange={e => setWaitlistForm({ ...waitlistForm, unit_address: e.target.value })} /></div>
|
||||
<div>
|
||||
<Label>Lot type</Label>
|
||||
<Select value={waitlistForm.requested_lot_type} onValueChange={v => setWaitlistForm({ ...waitlistForm, requested_lot_type: v })}>
|
||||
<SelectTrigger><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="rv">RV</SelectItem>
|
||||
<SelectItem value="boat">Boat</SelectItem>
|
||||
<SelectItem value="either">Either</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div><Label>Size</Label><Input placeholder="e.g. 30 ft, 10x30" value={waitlistForm.requested_size} onChange={e => setWaitlistForm({ ...waitlistForm, requested_size: e.target.value })} /></div>
|
||||
<div><Label>Vehicle description</Label><Input value={waitlistForm.vehicle_description} onChange={e => setWaitlistForm({ ...waitlistForm, vehicle_description: e.target.value })} /></div>
|
||||
<div><Label>Notes</Label><Textarea value={waitlistForm.notes} onChange={e => setWaitlistForm({ ...waitlistForm, notes: e.target.value })} /></div>
|
||||
</div>
|
||||
@@ -465,7 +469,7 @@ export default function RVBoatLotsPage() {
|
||||
<TableHead className="w-16">#</TableHead>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Contact</TableHead>
|
||||
<TableHead>Type</TableHead>
|
||||
<TableHead>Size</TableHead>
|
||||
<TableHead>Joined</TableHead>
|
||||
<TableHead>Source</TableHead>
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
@@ -483,7 +487,7 @@ export default function RVBoatLotsPage() {
|
||||
{w.requester_email && <div>{w.requester_email}</div>}
|
||||
{w.requester_phone && <div>{w.requester_phone}</div>}
|
||||
</TableCell>
|
||||
<TableCell><Badge variant="outline">{w.requested_lot_type}</Badge></TableCell>
|
||||
<TableCell className="text-sm">{w.requested_size || "—"}</TableCell>
|
||||
<TableCell className="text-xs">{new Date(w.joined_at).toLocaleDateString()}</TableCell>
|
||||
<TableCell><Badge variant="secondary">{w.source === "public_form" ? "Public" : "Manual"}</Badge></TableCell>
|
||||
<TableCell className="text-right space-x-1">
|
||||
@@ -520,9 +524,7 @@ export default function RVBoatLotsPage() {
|
||||
<Select value={lotForm.lot_type} onValueChange={v => setLotForm({ ...lotForm, lot_type: v })}>
|
||||
<SelectTrigger><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="rv">RV</SelectItem>
|
||||
<SelectItem value="boat">Boat</SelectItem>
|
||||
<SelectItem value="either">Either</SelectItem>
|
||||
{VEHICLE_TYPES.map(t => <SelectItem key={t.value} value={t.value}>{t.label}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@@ -562,7 +564,7 @@ export default function RVBoatLotsPage() {
|
||||
<TableRow key={lot.id}>
|
||||
<TableCell><Checkbox aria-label={`Select lot ${lot.lot_number}`} checked={selectedLotIds.has(lot.id)} onCheckedChange={() => toggleSet(setSelectedLotIds, lot.id)} /></TableCell>
|
||||
<TableCell className="font-medium">{lot.lot_number}</TableCell>
|
||||
<TableCell><Badge variant="outline">{lot.lot_type}</Badge></TableCell>
|
||||
<TableCell><Badge variant="outline">{vehicleTypeLabel(lot.lot_type)}</Badge></TableCell>
|
||||
<TableCell>{lot.size || "-"}</TableCell>
|
||||
<TableCell>{lot.monthly_rate ? `$${lot.monthly_rate}` : "-"}</TableCell>
|
||||
<TableCell>
|
||||
@@ -827,9 +829,7 @@ export default function RVBoatLotsPage() {
|
||||
<SelectTrigger><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="no_change">No change</SelectItem>
|
||||
<SelectItem value="rv">RV</SelectItem>
|
||||
<SelectItem value="boat">Boat</SelectItem>
|
||||
<SelectItem value="either">Either</SelectItem>
|
||||
{VEHICLE_TYPES.map(t => <SelectItem key={t.value} value={t.value}>{t.label}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- RV/Boat waitlist: capture requested lot size (replaces "type" in the internal UI).
|
||||
alter table public.rv_boat_lot_waitlist add column if not exists requested_size text;
|
||||
Reference in New Issue
Block a user