Untitled
unknown
plain_text
2 months ago
5.8 kB
6
No Index
//wrangler.toml
name = "tshirt"
compatibility_flags = ["nodejs_compat"]
compatibility_date = "2024-09-23"
[[r2_buckets]]
binding = "tshirtbucket"
bucket_name = "tshirt"
preview_bucket_name = "tshirt"
[[hyperdrive]]
binding = "hyperdrive"
id = "35d40131da5f460f9aa0146b260f8bf4"
----------------------------------------------------------------------------------------------
//src/lib/db.ts
import { Kysely, PostgresDialect } from 'kysely';
import { Pool, Client } from 'pg';
import { cache } from 'react';
import { getCloudflareContext } from '@opennextjs/cloudflare';
export interface Database {
products: {
id: string // UUID
name: string
description: string | null
category_id: string // UUID
price: number // DECIMAL mapped to number
discount: number | null
gender: 'men' | 'women' | 'unisex'
public_id: string
is_active: boolean
created_at: Date
}
product_variants: {
id: number // INT
product_id: string // UUID
size: string
color: string
stock: number
}
product_images: {
product_id: string // UUID
variant_id: number // INT
rank: number
path: string
}
}
export const getKyselyDb = cache(() => {
const { env } = getCloudflareContext();
const connectionString = env.hyperdrive.connectionString;
const pool = new Pool({
connectionString,
max: 5, // Max connections per Worker request
maxUses: 1, // Do not reuse connections across requests
});
return new Kysely<Database>({
dialect: new PostgresDialect({ pool }),
});
});
-----------------------------------------------------------------------------------------------
//src/app/product/[itemid]/page.tsx
import {splitUuidVariant} from '@/utils/helper';
import {getKyselyDb, Database} from '@/lib/db';
import Image from 'next/image';
import { Button } from '@/components/ui/button';
export const fetchCache = 'force-no-store';
export const runtime = 'edge';
export default async function ItemRoute({ params }: { params: { itemid: string } }) {
const res = splitUuidVariant(params.itemid);
if (!res) {
return <div>Invalid item ID</div>;
}
const [uuid, variant] = res;
let product: Database['products'] | null = null;
let variants: Database['product_variants'][] = [];
let images: Database['product_images'][] = [];
try {
({ product, variants, images } = await fetchItemDetails(uuid, variant));
} catch (error) {
console.error('Error fetching item details:', error);
return <div>Error loading item details. Please try again later.</div>;
}
if (!product || variants.length === 0 || images.length === 0) {
return <div>Item not found</div>;
}
// Render product details
return (
<div className="max-w-6xl mx-auto p-4 grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="space-y-4">
{images.map(img => (
<Image
key={img.product_id + '-' + img.variant_id + '-' + img.rank}
src={img.path}
alt={product?.name || 'Product image'}
width={500}
height={500}
className="rounded-lg border"
/>
))}
</div>
{/* Product Details */}
<div className="space-y-4">
<h1 className="text-3xl font-bold">{product.name}</h1>
{product.discount ? (
<div className="flex items-baseline space-x-2">
<span className="text-xl font-semibold text-red-600">${(product.price - product.discount).toFixed(2)}</span>
<span className="text-gray-400 line-through">${product.price.toFixed(2)}</span>
</div>
) : (
<div className="text-xl font-semibold">${product.price.toFixed(2)}</div>
)}
<p className="text-gray-700">{product.description}</p>
{/* Variant Selector */}
{variants.length > 1 && (
<div className="space-y-2">
<h3 className="font-semibold">Select Size & Color</h3>
<div className="flex flex-wrap gap-2">
{variants.map(v => (
<Button key={v.id} variant="outline" size="sm">
{v.size} - {v.color}
</Button>
))}
</div>
</div>
)}
{/* Add to Cart */}
<Button className="mt-4 w-full">Add to Cart</Button>
</div>
</div>
)
}
const fetchItemDetails = async (product_id: string, variant_id: number): Promise<{
product: Database['products'] | null;
variants: Database['product_variants'][];
images: Database['product_images'][];
}> => {
const db = getKyselyDb();
const [productResult, variants, images] = await Promise.all([
db.selectFrom('products')
.where('id', '=', product_id)
.selectAll()
.executeTakeFirst()??null,
db.selectFrom('product_variants')
.where('product_id', '=', product_id)
.where('id', '=', variant_id)
.selectAll()
.execute(),
db.selectFrom('product_images')
.where('product_id', '=', product_id)
.selectAll()
.execute(),
]);
const product = productResult ?? null;
return { product, variants, images };
}Editor is loading...
Leave a Comment