Skip to content

Commit

Permalink
Merge pull request #12 from ThomasJ0nes/populate-listingpage
Browse files Browse the repository at this point in the history
Populate listingpage
  • Loading branch information
ThomasJ0nes authored Aug 10, 2024
2 parents b27fc57 + 2edca36 commit 696dca3
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 57 deletions.
108 changes: 52 additions & 56 deletions packages/nextjs/app/listing-page/page.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,64 @@
import React from "react";
import Image from "next/image";
import ListingsList from "~~/components/ListingsList";
import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";

const PropertyForm: React.FC = () => {
const page = () => {
return (
<div className="flex flex-col space-y-8 p-4 mt-12">
{/* Second Section */}
<div className="flex flex-col lg:flex-row lg:space-x-4 mb-8 mt-12">
{/* Property Picture */}
<div className="flex-1 lg:flex-[0.25] relative h-64 bg-gray-200">
<Image width={300} height={300} src="/frame-1.png" alt="Property" className="w-full h-full object-cover" />
<>
<div className="relative isolate px-6 pt-14 lg:px-8">
<div
aria-hidden="true"
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
>
<div
style={{
clipPath:
"polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
}}
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
/>
</div>

{/* Property Details */}
<div className="flex-1 lg:flex-[0.75] flex flex-col space-y-4">
{/* Headline */}
<h2 className="text-xl font-bold mb-2">Available Properties</h2>

{/* Property Details */}
<div className="space-y-2">
<p>Notting Hill, London</p>
<p>Private | Date available: 02.07.2024 | Flat | 1 bed</p>
<p>$50 Per Night</p>
<p className="text-gray-500">Email: [email protected]</p>
<div className="mx-auto max-w-2xl py-1 sm:py-10 lg:py-20">
<div className="hidden sm:mb-8 sm:flex sm:justify-center">
<div className="relative rounded-full px-3 py-1 text-sm leading-6 ring-1 ring-gray-900/10 hover:ring-gray-900/20 dark:ring-gray-100">
Learn more about how 0xList Works.{" "}
<a href="#" className="font-semibold text-indigo-600 dark:text-indigo-300">
<span aria-hidden="true" className="absolute inset-0" />
Learn more <span aria-hidden="true">&rarr;</span>
</a>
</div>
</div>

{/* Mint to Contact the Owner Button */}
<div className="flex justify-end mt-auto">
<button className="btn btn-primary px-6 py-3 text-lg font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Mint to contact the owner
</button>
<div className="text-center">
<h1 className="text-4xl font-bold tracking-tight sm:text-6xl">Browse all On Chain Listings</h1>
<p className="mt-6 text-lg leading-8 ">
Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui lorem cupidatat commodo. Elit sunt amet
fugiat veniam occaecat fugiat aliqua.
</p>
<div className="mt-10 flex items-center justify-center gap-x-6">
<RainbowKitCustomConnectButton />
<a href="/createlisting" className="text-sm font-semibold leading-6 hover:underline">
List On Chain <span aria-hidden="true"></span>
</a>
</div>
</div>
</div>
</div>

{/* Third Section */}
<div className="flex flex-col lg:flex-row lg:space-x-4 mb-8 mt-12">
{/* Property Picture */}
<div className="flex-1 lg:flex-[0.25] relative h-64 bg-gray-200">
<Image width={300} height={300} src="/frame-1.png" alt="Property" className="w-full h-full object-cover" />
</div>

{/* Property Details */}
<div className="flex-1 lg:flex-[0.75] flex flex-col space-y-4">
{/* Headline */}
<h2 className="text-xl font-bold mb-2">Available Properties</h2>

{/* Property Details */}
<div className="space-y-2">
<p>Notting Hill, London</p>
<p>Private | Date available: 02.07.2024 | Flat | 1 bed</p>
<p>$50 Per Night</p>
<p className="text-gray-500">Email: [email protected]</p>
</div>

{/* Mint to Contact the Owner Button */}
<div className="flex justify-end mt-auto">
<button className="btn btn-primary px-6 py-3 text-lg font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Mint to contact the owner
</button>
</div>
<div
aria-hidden="true"
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
>
<div
style={{
clipPath:
"polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
}}
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
/>
</div>
</div>
</div>

<ListingsList />
</>
);
};

export default PropertyForm;
export default page;
121 changes: 121 additions & 0 deletions packages/nextjs/components/ListingsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"use client";

import React from "react";
import { useAccount } from "wagmi";
import { useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth";

// Skeleton Loader Component
const SkeletonLoader = () => {
return (
<li className="px-6 py-6 flex items-center space-x-6 animate-pulse">
<div className="w-1/3 h-32 bg-gray-300 rounded-md"></div>
<div className="w-2/3 flex flex-col space-y-2">
<div className="h-6 bg-gray-300 rounded"></div>
<div className="h-4 bg-gray-300 rounded w-1/2"></div>
<div className="h-4 bg-gray-300 rounded w-1/3"></div>
<div className="mt-auto flex justify-end">
<div className="h-10 w-24 bg-gray-300 rounded"></div>
</div>
</div>
</li>
);
};

export const ListingsList = () => {
// Fetch all listings from the contract
const {
data: listings,
isLoading,
error,
} = useScaffoldReadContract({
contractName: "Listings",
functionName: "getAllListings",
});

const { address } = useAccount();

const { writeContractAsync, isMining } = useScaffoldWriteContract("Listings");

const handleMintToContact = async (listingId: number) => {
try {
await writeContractAsync({
functionName: "createListingConnection",
args: [BigInt(listingId)],
});
alert("Successfully created a connection!");
} catch (err) {
console.error("Error creating listing connection:", err);
alert("Failed to create a connection. See console for details.");
}
};

// Render loading state with skeletons
if (isLoading) {
return (
<div className="flex justify-center mt-12 px-4">
<div className="w-full max-w-7xl overflow-hidden rounded-m shadow">
<ul role="list" className="divide-y divide-gray-200">
{Array(3)
.fill(0)
.map((_, index) => (
<SkeletonLoader key={index} />
))}
</ul>
</div>
</div>
);
}

// Render error state
if (error) {
return <div className="flex justify-center items-center h-full">Error loading listings: {error.message}</div>;
}

return (
<div className="flex justify-center mt-12 px-4">
<div className="w-full max-w-7xl overflow-hidden rounded-m shadow">
<ul role="list" className="divide-y divide-gray-200">
{listings?.map((listing: any, index: number) => (
<li key={index} className="px-6 py-6 flex items-center space-x-6">
{/* Property Picture */}
<div className="w-1/3 h-100">
<img
className="w-full h-full rounded-md object-cover"
src={`https://${process.env.NEXT_PUBLIC_GATEWAY_URL}/ipfs/${listing.cid}`}
alt={listing.name}
/>
</div>

{/* Property Details */}
<div className="w-2/3 flex flex-col justify-between space-y-2">
<div>
<h2 className="text-xl font-bold">{listing.name}</h2>
<p className="text-lg">
Location: <strong>{listing.location}</strong>
</p>
</div>
<p className="text-base">{listing.description}</p>
<p className="text-base mt-2">
Price: {listing.price.toString()} | Beds: {listing.beds.toString()}
</p>
<div className="flex justify-end">
<button
className={`btn btn-primary px-4 py-2 text-base font-semibold rounded-md shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 ${
isMining ? "loading" : ""
}`}
onClick={() => handleMintToContact(listing.id)}
disabled={isMining || address === listing.seller}
>
{isMining ? "Minting..." : "Mint to contact the owner"}
</button>
</div>
</div>
</li>
))}
</ul>
</div>
</div>
);
};

export default ListingsList;
3 changes: 2 additions & 1 deletion packages/nextjs/components/account/TabNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import MyAccount from "./MyAccount";
import MyListings from "./MyListings";
import RecentBookings from "./RecentBookings";
import Transactions from "./Transactions";
import { Gauge } from "lucide-react";

const TabNav = () => {
Expand Down Expand Up @@ -56,7 +57,7 @@ const TabNav = () => {
aria-label="My Transactions"
/>
<div role="tabpanel" className="tab-content bg-base-100 border-base-300 rounded-box p-6">
Tab content 4
<Transactions />
</div>
</div>
</div>
Expand Down
16 changes: 16 additions & 0 deletions packages/nextjs/components/account/Transactions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const items = [
{ id: 1 },
// More items...
];

export default function Transactions() {
return (
<ul role="list" className="divide-y divide-gray-200">
{items.map(item => (
<li key={item.id} className="py-4">
{/* Your content */}
</li>
))}
</ul>
);
}
Binary file added packages/nextjs/public/Logo0xList.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 696dca3

Please sign in to comment.