From 3483f29afafbe2b02c4c106267b97ea3d0a5eb25 Mon Sep 17 00:00:00 2001 From: asabizanjo Date: Thu, 20 Nov 2025 21:11:55 +0000 Subject: [PATCH] list partially done. UI changes needed, UX is good --- src/app/page.tsx | 3 +- src/components/list-property/list.tsx | 587 ++++++++++++++++++++++++++ 2 files changed, 589 insertions(+), 1 deletion(-) create mode 100644 src/components/list-property/list.tsx diff --git a/src/app/page.tsx b/src/app/page.tsx index 2b2d483..f17b4ea 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -9,12 +9,13 @@ import Footer from "@/components/landing/footer"; import SearchBy from "@/components/search-results/search"; import Results from "@/components/search-results/results"; import Features from "@/components/details/features"; +import List from "@/components/list-property/list"; export default function Home() { return ( <>
- +
diff --git a/src/components/list-property/list.tsx b/src/components/list-property/list.tsx new file mode 100644 index 0000000..cd26c97 --- /dev/null +++ b/src/components/list-property/list.tsx @@ -0,0 +1,587 @@ +"use client"; + +import { useState, useRef } from "react"; +import localFont from "next/font/local"; +import gsap from "gsap"; +import { useGSAP } from "@gsap/react"; +import { + House, + Buildings, + Farm, + Bed, + MapPin, + Camera, + WifiHigh, + Article, + CurrencyDollar, + CheckCircle, + CalendarBlank, + ShieldCheck, + CaretLeft, + CaretRight +} from "@phosphor-icons/react"; + +const figtree = localFont({ + src: [ + { + path: '../../../public/Fonts/figtree/figtree.ttf', + }, + ], +}) + +// Shared styles +const containerStyle = `flex flex-col gap-6 w-full max-w-xl mx-auto`; +const titleStyle = `${figtree.className} text-3xl font-bold mb-4`; +const inputStyle = `${figtree.className} w-full p-4 border-2 border-black text-lg outline-none focus:bg-gray-50 transition-colors`; +const buttonStyle = `${figtree.className} flex items-center justify-center gap-2 px-8 py-3 border-2 border-black bg-[#E7FE78] text-lg font-medium hover:bg-[#dcfc4e] transition-colors disabled:opacity-50 disabled:cursor-not-allowed`; +const secondaryButtonStyle = `${figtree.className} flex items-center justify-center gap-2 px-8 py-3 border-2 border-black bg-white text-lg font-medium hover:bg-gray-50 transition-colors`; +const optionCardStyle = (selected: boolean) => + `flex flex-col items-center justify-center gap-3 p-6 border-2 border-black cursor-pointer transition-all hover:bg-gray-50 ${selected ? 'bg-[#E7FE78]' : 'bg-white'}`; + +interface FormData { + propertyType?: string; + placeType?: string; + location?: string; + guests?: number; + bedrooms?: number; + beds?: number; + bathrooms?: number; + amenities?: string[]; + description?: string; + price?: string; + instantBook?: boolean; + safety?: string[]; +} + +type FormValue = string | number | boolean | string[] | undefined; + +interface StepProps { + onNext: () => void; + onBack: () => void; + data: FormData; + updateData: (key: keyof FormData, value: FormValue) => void; +} + +/* Property Type */ +const PropertyType = ({ onNext, data, updateData }: StepProps) => { + const types = [ + { id: 'house', label: 'House', icon: House }, + { id: 'flat', label: 'Flat', icon: Buildings }, + { id: 'farmhouse', label: 'Farmhouse', icon: Farm }, + { id: 'guesthouse', label: 'Guesthouse', icon: Bed }, + ]; + + const handleSelect = (id: string) => { + updateData('propertyType', id); + onNext(); + }; + + return ( +
+

What kind of place will you host?

+
+ {types.map((type) => ( + + ))} +
+
+ ) +} + +/* Property Place Type */ +const PropertyPlaceType = ({ onNext, onBack, data, updateData }: StepProps) => { + const places = [ + { id: 'entire', label: 'An entire place', description: 'Guests have the whole place to themselves.' }, + { id: 'room', label: 'A room', description: 'Guests have their own room in a home, plus access to shared spaces.' }, + { id: 'shared', label: 'A shared room', description: 'Guests sleep in a room or common area that may be shared with others.' }, + ]; + + const handleSelect = (id: string) => { + updateData('placeType', id); + onNext(); + }; + + return ( +
+

What type of place will guests have?

+
+ {places.map((place) => ( + + ))} +
+
+ +
+
+ ) +} + +/* Property Location */ +const PropertyLocation = ({ onNext, onBack, data, updateData }: StepProps) => { + return ( +
+

Where's your place located?

+
+
+ + updateData('location', e.target.value)} + /> +
+ {/* Placeholder for map */} +
+ Map Preview +
+
+
+ + +
+
+ ) +} + +/* Property Capacity */ +const PropertyCapacity = ({ onNext, onBack, data, updateData }: StepProps) => { + const counters: { key: keyof FormData; label: string }[] = [ + { key: 'guests', label: 'Guests' }, + { key: 'bedrooms', label: 'Bedrooms' }, + { key: 'beds', label: 'Beds' }, + { key: 'bathrooms', label: 'Bathrooms' }, + ]; + + const updateCount = (key: keyof FormData, delta: number) => { + const current = (data[key] as number) || 0; + updateData(key, Math.max(0, current + delta)); + }; + + return ( +
+

Share some basics about your place

+
+ {counters.map((item) => ( +
+ {item.label} +
+ + {data[item.key] || 0} + +
+
+ ))} +
+
+ + +
+
+ ) +} + +/* Property Photos */ +const PropertyPhotos = ({ onNext, onBack }: StepProps) => { + return ( +
+

Add some photos of your house

+
+ +
+

Drag your photos here

+

Choose at least 5 photos

+
+ +
+
+ + +
+
+ ) +} + +/* Property Amenities */ +const PropertyAmenities = ({ onNext, onBack, data, updateData }: StepProps) => { + const amenities = [ + { id: 'wifi', label: 'Wi-Fi', icon: WifiHigh }, + { id: 'kitchen', label: 'Kitchen', icon: House }, + { id: 'parking', label: 'Free parking', icon: Farm }, + { id: 'pool', label: 'Pool', icon: Buildings }, + ]; + + const toggleAmenity = (id: string) => { + const current = data.amenities || []; + const updated = current.includes(id) + ? current.filter((item: string) => item !== id) + : [...current, id]; + updateData('amenities', updated); + }; + + return ( +
+

What does your place offer?

+
+ {amenities.map((amenity) => ( + + ))} +
+
+ + +
+
+ ) +} + +/* Property Description */ +const PropertyDescription = ({ onNext, onBack, data, updateData }: StepProps) => { + return ( +
+

How would you describe your place?

+
+