feat(F-067): completed feature
This commit is contained in:
40
project/frontend/src/app/api/users/[id]/addresses/route.ts
Normal file
40
project/frontend/src/app/api/users/[id]/addresses/route.ts
Normal 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 });
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
) : (
|
||||
|
||||
@@ -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" />
|
||||
) : (
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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" />
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user