Skip to content

Commit

Permalink
feat: implement product page
Browse files Browse the repository at this point in the history
  • Loading branch information
kang-kibong committed Jul 19, 2024
1 parent 93c3b3c commit 8870181
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 57 deletions.
3 changes: 2 additions & 1 deletion src/apis/products/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { ProductDetailResponse } from '@internalTypes/responseTypes';
import axiosInstance from '../instance';
import { PRODUCTS_PATHS } from './path';

export const getProductsDetail = async (params: ProductDetailRequest): Promise<ProductDetailResponse> => {
export const getProductsDetail = async (params?: ProductDetailRequest): Promise<ProductDetailResponse> => {
if (!params) throw new Error('params is required');
const { productId } = params;

const res = await axiosInstance.get<ProductDetailResponse>(PRODUCTS_PATHS.PRODUCTS_DETAIL(productId));
Expand Down
4 changes: 2 additions & 2 deletions src/apis/products/path.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const API_BASE = '/api/v1';

export const PRODUCTS_PATHS = {
PRODUCTS_DETAIL: (productId: string) => `${API_BASE}/products/${productId}/detail`,
PRODUCTS_OPTIONS: (productId: string) => `${API_BASE}/products/${productId}/options`,
PRODUCTS_DETAIL: (productId?: string) => `${API_BASE}/products/${productId}/detail`,
PRODUCTS_OPTIONS: (productId?: string) => `${API_BASE}/products/${productId}/options`,
};
2 changes: 1 addition & 1 deletion src/apis/themes/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ const API_BASE = '/api/v1';

export const THEME_PATHS = {
THEMES: `${API_BASE}/themes`,
THEME_PRODUCTS: (themeKey: string) => `${API_BASE}/themes/${themeKey}/products`,
THEME_PRODUCTS: (themeKey?: string) => `${API_BASE}/themes/${themeKey}/products`,
};
16 changes: 11 additions & 5 deletions src/components/features/Product/ProductInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import styled from '@emotion/styled';
import React from 'react';
import { Image } from '@chakra-ui/react';

import { Container } from '@components/common';
import ProductImage from '@assets/images/goodsItem.jpg';

const IMAGE_SIZE = 450;

export default function ProductInfo() {
interface ProductInfoProps {
image?: string;
name?: string;
price?: number;
}

export default function ProductInfo({ image, name, price }: ProductInfoProps) {
return (
<ProductContainer>
<article>
<Container justifyContent="space-between">
<Image src={ProductImage} maxW={IMAGE_SIZE} maxH={IMAGE_SIZE} mr={6} />
<Image src={image} maxW={IMAGE_SIZE} maxH={IMAGE_SIZE} mr={6} />
<div>
<ProductTitle>[단독각인] 피렌체 1221 에디션 오드코롱 50ml (13종 택1)</ProductTitle>
<ProductPrice>145000원</ProductPrice>
<ProductTitle>{name}</ProductTitle>
<ProductPrice>{price}</ProductPrice>
<GiftInfo>
<hr />
<p>카톡 친구가 아니어도 선물 코드로 선물 할 수 있어요!</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import styled from '@emotion/styled';
import { Input, Button, useNumberInput, HStack } from '@chakra-ui/react';

export default function QuantitySelector() {
Expand All @@ -14,27 +13,10 @@ export default function QuantitySelector() {
const input = getInputProps();

return (
<QuantitySelectorConatiner>
<Title>[단독각인] 피렌체 1221 에디션 오드코롱 50ml (13종 택1)</Title>
<HStack maxW="320px">
<Button {...dec}>-</Button>
<Input {...input} />
<Button {...inc}>+</Button>
</HStack>
</QuantitySelectorConatiner>
<HStack maxW="320px">
<Button {...dec}>-</Button>
<Input {...input} />
<Button {...inc}>+</Button>
</HStack>
);
}

const QuantitySelectorConatiner = styled.div`
display: flex;
flex-direction: column;
align-items: center;
padding: 12px 14px 16px;
border: 1px solid rgb(237, 237, 237);
border-radius: 2px;
`;

const Title = styled.p`
font-weight: 700;
margin-bottom: 12px;
`;
25 changes: 23 additions & 2 deletions src/components/features/Product/ProductOrder/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import { useAuth } from '@context/auth/useAuth';
import { Button } from '@components/common';
import QuantitySelector from './QuantitySelector';

export default function ProductOrder() {
interface ProductOrderProps {
name?: string;
}

export default function ProductOrder({ name }: ProductOrderProps) {
const { isAuthenticated } = useAuth();
const navigate = useNavigate();

Expand All @@ -17,7 +21,10 @@ export default function ProductOrder() {

return (
<ProductOrderContainer>
<QuantitySelector />
<QuantitySelectorConatiner>
<Title>{name}</Title>
<QuantitySelector />
</QuantitySelectorConatiner>
<div>
<TotalAmount>
<dl>
Expand All @@ -40,6 +47,20 @@ const ProductOrderContainer = styled.aside`
max-width: 360px;
`;

const QuantitySelectorConatiner = styled.div`
display: flex;
flex-direction: column;
align-items: center;
padding: 12px 14px 16px;
border: 1px solid rgb(237, 237, 237);
border-radius: 2px;
`;

const Title = styled.p`
font-weight: 700;
margin-bottom: 12px;
`;

const TotalAmount = styled.div`
padding: 18px 20px;
border-radius: 4px;
Expand Down
14 changes: 12 additions & 2 deletions src/pages/Product/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,26 @@ import ProductInfo from '@components/features/Product/ProductInfo';
import ProductOrder from '@components/features/Product/ProductOrder';
import { ROUTE_PATH } from '@routes/path';
import useRedirectIfNoParam from '@hooks/useRedirectIfNoParam';
import { useQuery } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';
import { getProductsDetail } from '@/apis/products';
import { ProductDetailResponse } from '@internalTypes/responseTypes';
import { AxiosError } from 'axios';

export default function Product() {
const { productId } = useParams<{ productId: string }>();
const { data } = useQuery<ProductDetailResponse, AxiosError>({
queryKey: ['productDetail', productId],
queryFn: () => getProductsDetail({ productId }),
});
useRedirectIfNoParam('productId', ROUTE_PATH.HOME);

return (
<Layout>
<CenteredContainer maxWidth="lg">
<InnerContainer>
<ProductInfo />
<ProductOrder />
<ProductInfo image={data?.detail.imageURL} name={data?.detail.name} price={data?.detail.price.basicPrice} />
<ProductOrder name={data?.detail.name} />
</InnerContainer>
</CenteredContainer>
</Layout>
Expand Down
2 changes: 1 addition & 1 deletion src/types/requestTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface ThemeProductsRequest {
}

export interface ProductDetailRequest {
productId: string;
productId?: string;
}

export interface ProductOptionsRequest {
Expand Down
42 changes: 22 additions & 20 deletions src/types/responseTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,28 @@ export interface ThemeProductsResponse {
};
}

export interface ProductDetailResponse extends ProductData {
isAccessableProductPage: boolean;
review: {
averageRating: number;
totalReviewCount: number;
};
productDescription: {
images: string[];
};
productDetailInfo: {
announcements: {
displayOrder: number;
name: string;
value: string;
}[];
terms: {
displayOrder: number;
title: string;
description: string;
}[];
export interface ProductDetailResponse {
detail: ProductData & {
isAccessableProductPage: boolean;
review: {
averageRating: number;
totalReviewCount: number;
};
productDescription: {
displayImage: string;
};
productDetailInfo: {
announcements: {
name: string;
value: string;
displayOrder: number;
}[];
terms: {
displayCode: string;
title: string;
description: string;
}[];
};
};
}

Expand Down

0 comments on commit 8870181

Please sign in to comment.