feat(F-067): completed feature

This commit is contained in:
chattie
2026-08-19 17:30:00 +02:00
parent 9f1858f6d7
commit f62bd6a578
16 changed files with 416 additions and 24 deletions

View File

@@ -0,0 +1,40 @@
import { NextRequest, NextResponse } from 'next/server';
const API = process.env.NEXT_PUBLIC_API_URL ?? 'http://127.0.0.1:3000';
interface RouteParams {
params: Promise<{ id: string }>;
}
export async function GET(_request: NextRequest, { params }: RouteParams) {
const { id } = await params;
const cookie = _request.headers.get('cookie') ?? '';
try {
const res = await fetch(`${API}/users/${id}/addresses`, {
headers: { Cookie: cookie },
cache: 'no-store',
});
const body = await res.json().catch(() => ({ items: [] }));
return NextResponse.json(body, { status: res.status });
} catch {
return NextResponse.json({ items: [] }, { status: 502 });
}
}
export async function POST(request: NextRequest, { params }: RouteParams) {
const { id } = await params;
const cookie = request.headers.get('cookie') ?? '';
const payload = await request.text();
try {
const res = await fetch(`${API}/users/${id}/addresses`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Cookie: cookie },
body: payload,
cache: 'no-store',
});
const body = await res.json().catch(() => ({}));
return NextResponse.json(body, { status: res.status });
} catch {
return NextResponse.json({ error: 'Proxy error' }, { status: 502 });
}
}

View File

@@ -79,7 +79,7 @@ export default async function BrandPage({ params }: Props) {
{products.map((product) => (
<Link key={product.id} href={`/products/${product.slug}`} className="group block">
<div className="bg-gray-50 rounded-xl overflow-hidden border border-gray-100 hover:border-[#70ad47] transition-all hover:shadow-md">
<div className="relative aspect-[5/7] max-h-72 bg-white flex items-center justify-center overflow-hidden">
<div className="relative w-full max-h-72 bg-white flex items-center justify-center overflow-hidden">
{product.images?.[0] ? (
<Image src={product.images[0].url} alt={product.name} fill className="object-contain" sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw" />
) : (

View File

@@ -87,7 +87,7 @@ export default async function CategoryPage({ params }: Props) {
{products.map((product) => (
<Link key={product.id} href={`/products/${product.slug}`} className="group block">
<div className="bg-gray-50 rounded-xl overflow-hidden border border-gray-100 hover:border-[#70ad47] transition-all hover:shadow-md">
<div className="relative aspect-[5/7] max-h-72 bg-white flex items-center justify-center overflow-hidden">
<div className="relative w-full max-h-72 bg-white flex items-center justify-center overflow-hidden">
{product.images?.[0] ? (
<Image src={product.images[0].url} alt={product.name} fill className="object-contain" sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw" />
) : (

View File

@@ -48,11 +48,10 @@ export default async function ProductsPage() {
return (
<Link key={product.id} href={`/products/${product.slug}`} className="group block">
<div className="bg-gray-50 rounded-xl overflow-hidden border border-gray-100 hover:border-[#70ad47] transition-all hover:shadow-md">
{/* Image container: bounded box (max 5:7 aspect ratio to match
backend thumbnail sizing). The image preserves its source
aspect ratio via `object-contain`, so non-square images
display without cropping. */}
<div className="relative aspect-[5/7] max-h-72 bg-white flex items-center justify-center overflow-hidden">
{/* Image container fills the card width; the image itself
is centred with `object-contain`. The bounding box is
capped at max-h-72 so very tall images don't dominate. */}
<div className="relative w-full max-h-72 bg-white flex items-center justify-center overflow-hidden">
{product.images?.[0] ? (
<Image
src={product.images[0].url}

View File

@@ -92,7 +92,7 @@ export default async function SearchPage({ searchParams }: Props) {
return (
<Link key={product.id} href={`/products/${product.slug}`} className="group block">
<div className="bg-gray-50 rounded-xl overflow-hidden border border-gray-100 hover:border-[#70ad47] transition-all hover:shadow-md">
<div className="relative aspect-[5/7] max-h-72 bg-white flex items-center justify-center overflow-hidden">
<div className="relative w-full max-h-72 bg-white flex items-center justify-center overflow-hidden">
{product.images?.[0] ? (
<Image src={product.images[0].url} alt={product.name} fill className="object-contain" sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw" />
) : (