From 6247da1c990f672677d545fbbc9b07551a5ed0d6 Mon Sep 17 00:00:00 2001
From: kimdaye77 <63107805+kimdaye77@users.noreply.github.com>
Date: Fri, 18 Aug 2023 16:25:43 +0900
Subject: [PATCH 1/7] =?UTF-8?q?[STYLE]=20#295:=20=EA=B8=80=EC=9E=90=20?=
=?UTF-8?q?=ED=81=AC=EA=B8=B0=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/src/components/cards/ModelTypeCard.tsx | 4 ++--
frontend/src/components/cards/OptionCard.tsx | 4 ++--
frontend/src/components/common/banner/Banner.tsx | 1 -
frontend/src/components/tabs/OptionTab.tsx | 16 ++++++++++++----
4 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/frontend/src/components/cards/ModelTypeCard.tsx b/frontend/src/components/cards/ModelTypeCard.tsx
index 8063d63..ff79995 100644
--- a/frontend/src/components/cards/ModelTypeCard.tsx
+++ b/frontend/src/components/cards/ModelTypeCard.tsx
@@ -1,6 +1,6 @@
import { styled } from 'styled-components';
import { CheckIcon } from '../common/icons/Icons';
-import { BodyKrRegular4, HeadingEn4, HeadingKrMedium7 } from '../../styles/typefaces';
+import { BodyKrRegular4, HeadingKrMedium6, HeadingKrMedium7 } from '../../styles/typefaces';
import DefaultCardStyle from '../common/card/DefaultCardStyle';
import { HTMLAttributes } from 'react';
@@ -35,7 +35,7 @@ const Wrapper = styled(DefaultCardStyle)`
`;
const ModelTypeTitle = styled.div`
- ${HeadingEn4}
+ ${HeadingKrMedium6}
`;
const ModelTypePrice = styled.div`
${HeadingKrMedium7}
diff --git a/frontend/src/components/cards/OptionCard.tsx b/frontend/src/components/cards/OptionCard.tsx
index f112924..f8588b9 100644
--- a/frontend/src/components/cards/OptionCard.tsx
+++ b/frontend/src/components/cards/OptionCard.tsx
@@ -1,5 +1,5 @@
import { styled } from 'styled-components';
-import { BodyKrRegular4, HeadingEn4, HeadingKrMedium7 } from '../../styles/typefaces';
+import { BodyKrRegular4, HeadingKrMedium6, HeadingKrMedium7 } from '../../styles/typefaces';
import { CheckIcon } from '../common/icons/Icons';
import DefaultCardStyle from '../common/card/DefaultCardStyle';
import { HTMLAttributes } from 'react';
@@ -97,7 +97,7 @@ const OptionCardInfo = styled.div`
`;
const OptionTitle = styled.div`
- ${HeadingEn4}
+ ${HeadingKrMedium6}
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
diff --git a/frontend/src/components/common/banner/Banner.tsx b/frontend/src/components/common/banner/Banner.tsx
index 4968c73..59a8bfe 100644
--- a/frontend/src/components/common/banner/Banner.tsx
+++ b/frontend/src/components/common/banner/Banner.tsx
@@ -47,7 +47,6 @@ const SubTitle = styled.p`
const Title = styled.p`
position: relative;
- z-index: 3;
color: ${({ theme }) => theme.color.primaryColor700};
${HeadingKrBold1}
`;
diff --git a/frontend/src/components/tabs/OptionTab.tsx b/frontend/src/components/tabs/OptionTab.tsx
index 25d5c32..9e64a0a 100644
--- a/frontend/src/components/tabs/OptionTab.tsx
+++ b/frontend/src/components/tabs/OptionTab.tsx
@@ -1,4 +1,12 @@
-import { Dispatch, HTMLAttributes, SetStateAction, useEffect, useRef, useState } from 'react';
+import {
+ Dispatch,
+ Fragment,
+ HTMLAttributes,
+ SetStateAction,
+ useEffect,
+ useRef,
+ useState,
+} from 'react';
import { BodyKrMedium3, BodyKrRegular3, BodyKrRegular4 } from '../../styles/typefaces';
import styled, { css, useTheme } from 'styled-components';
import { ArrowLeft, ArrowRight } from '../common/icons/Icons';
@@ -92,8 +100,8 @@ export default function OptionTab({ options, setBannerInfo }: ISubOptionTab) {
{chunkedOptions.map((optionGroup: ISubOptionList[], groupIndex) => (
- <>
-
+
+
{optionGroup.map((option: ISubOptionList, index: number) => (
))}
- >
+
))}
From 6733a71266f76550349c31bd93a5b2526132278a Mon Sep 17 00:00:00 2001
From: jijiseong
Date: Sat, 19 Aug 2023 14:04:51 +0900
Subject: [PATCH 2/7] =?UTF-8?q?[FEAT]=20#315:=20=EA=B2=AC=EC=A0=81?=
=?UTF-8?q?=EC=9A=94=EC=95=BD=20UI?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/src/App.tsx | 2 +
.../common/buttons/ToggleButtons.tsx | 45 ++++
frontend/src/components/details/Details.tsx | 9 +-
.../src/components/details/SummaryItem.tsx | 3 +-
.../components/modal/QuoteSummaryModal.tsx | 209 ++++++++++++++
frontend/src/components/modal/WhiteModal.tsx | 18 ++
.../src/components/summary/PriceSummary.tsx | 14 +-
.../src/containers/Modal/ModalContainer.tsx | 4 +
.../OuterColorBannerContainer.tsx | 27 +-
.../OuterColorSelectContainer.tsx | 9 +-
.../containers/ResultPage/DetailContainer.tsx | 254 +++++++-----------
.../ResultPage/ResultFooterContainer.tsx | 6 +-
frontend/src/context/ItemProvider.tsx | 8 +-
frontend/src/context/OuterColorProvider.tsx | 25 +-
.../src/context/QuoteSummaryModalProvider.tsx | 27 ++
frontend/src/pages/OuterColorPage.tsx | 19 +-
16 files changed, 470 insertions(+), 209 deletions(-)
create mode 100644 frontend/src/components/common/buttons/ToggleButtons.tsx
create mode 100644 frontend/src/components/modal/QuoteSummaryModal.tsx
create mode 100644 frontend/src/components/modal/WhiteModal.tsx
create mode 100644 frontend/src/context/QuoteSummaryModalProvider.tsx
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 1a7d7b2..1736254 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -9,6 +9,7 @@ import SimilarQuoteModalProvider from './context/SimilarQuoteModalProvider';
import GuideModalProvider from './context/GuideModalProvider';
import ItemProvider from './context/ItemProvider';
import { useEffect } from 'react';
+import QuoteSummaryModalProvider from './context/QuoteSummaryModalProvider';
function App() {
useEffect(() => {
@@ -19,6 +20,7 @@ function App() {
CloseModalProvider,
SimilarQuoteModalProvider,
GuideModalProvider,
+ QuoteSummaryModalProvider,
ItemProvider,
];
return (
diff --git a/frontend/src/components/common/buttons/ToggleButtons.tsx b/frontend/src/components/common/buttons/ToggleButtons.tsx
new file mode 100644
index 0000000..e17fe27
--- /dev/null
+++ b/frontend/src/components/common/buttons/ToggleButtons.tsx
@@ -0,0 +1,45 @@
+import { styled } from 'styled-components';
+import { BodyKrRegular3 } from '../../../styles/typefaces';
+import { flexCenterCss } from '../../../utils/commonStyle';
+import { useState } from 'react';
+
+type buttonType = 'outerColor' | 'innerColor';
+
+export default function ToggleButtons() {
+ const [selectedButton, setSelectedButton] = useState('outerColor');
+
+ const toggle = () => {
+ if (selectedButton === 'outerColor') {
+ setSelectedButton('innerColor');
+ } else {
+ setSelectedButton('outerColor');
+ }
+ };
+
+ return (
+
+
+
+
+ );
+}
+
+const Button = styled.button<{ $active: boolean }>`
+ width: 100%;
+ ${BodyKrRegular3}
+ height: 36px;
+ border-radius: 18px;
+ color: ${({ $active, theme }) => ($active ? theme.color.white : theme.color.primaryColor)};
+ background-color: ${({ $active, theme }) => ($active ? theme.color.primaryColor : 'none')};
+`;
+const ToggleButtonContainer = styled.div`
+ ${flexCenterCss}
+ justify-content: space-between;
+ padding: 0 5px;
+ gap: 5px;
+ width: 213px;
+ height: 48px;
+ border-radius: 24px;
+ border: 1px solid ${({ theme }) => theme.color.gray100};
+ cursor: pointer;
+`;
diff --git a/frontend/src/components/details/Details.tsx b/frontend/src/components/details/Details.tsx
index f933f61..56896e3 100644
--- a/frontend/src/components/details/Details.tsx
+++ b/frontend/src/components/details/Details.tsx
@@ -1,24 +1,24 @@
import { styled, useTheme } from 'styled-components';
import { HTMLAttributes } from 'react';
-import { HeadingKrMedium5 } from '../../styles/typefaces';
+import { BodyKrMedium3, HeadingKrMedium5 } from '../../styles/typefaces';
import { ArrowDown, ArrowUp } from '../common/icons/Icons';
interface IDetails extends HTMLAttributes {
title: string;
open?: boolean;
+ desc: string;
}
-export default function Details({ title, open = false, ...props }: IDetails) {
+export default function Details({ title, open = false, desc, ...props }: IDetails) {
const theme = useTheme();
const arrowColor = theme.color.gray900;
- const totalPrice = 1_000_000;
return (
{title}
- +{totalPrice.toLocaleString()}원
+ {desc}
{open ? : }
@@ -46,6 +46,7 @@ const Price = styled.span`
margin-right: 20px;
`;
const RightDiv = styled.div`
+ ${BodyKrMedium3}
display: flex;
align-items: center;
color: ${({ theme }) => theme.color.primaryColor};
diff --git a/frontend/src/components/details/SummaryItem.tsx b/frontend/src/components/details/SummaryItem.tsx
index de0b99f..2dbd396 100644
--- a/frontend/src/components/details/SummaryItem.tsx
+++ b/frontend/src/components/details/SummaryItem.tsx
@@ -19,7 +19,7 @@ export default function SummaryItem({ imgSrc, itemName, selectedName, price }: I
수정하기
- + {price}원
+ + {price.toLocaleString()}원
@@ -62,5 +62,6 @@ const ItemName = styled.div`
`;
const ModifyButton = styled.button`
color: ${({ theme }) => theme.color.primaryColor};
+ text-align: end;
`;
const SelectedName = styled.div``;
diff --git a/frontend/src/components/modal/QuoteSummaryModal.tsx b/frontend/src/components/modal/QuoteSummaryModal.tsx
new file mode 100644
index 0000000..d201d7a
--- /dev/null
+++ b/frontend/src/components/modal/QuoteSummaryModal.tsx
@@ -0,0 +1,209 @@
+import { HTMLAttributes, useContext } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { styled } from 'styled-components';
+import { QuoteSummaryModalContext } from '../../context/QuoteSummaryModalProvider';
+import { PATH } from '../../utils/constants';
+import { ItemContext } from '../../context/ItemProvider';
+import RectButton from '../common/buttons/RectButton';
+import { CloseIcon } from '../common/icons/Icons';
+import ToggleButtons from '../common/buttons/ToggleButtons';
+import { flexCenterCss } from '../../utils/commonStyle';
+import {
+ BodyKrRegular3,
+ BodyKrRegular4,
+ HeadingKrMedium2,
+ HeadingKrMedium5,
+} from '../../styles/typefaces';
+import { DimmedBackground } from './DimmedBackground';
+import WhiteModal from './WhiteModal';
+
+interface IQuoteSummaryModal extends HTMLAttributes {}
+
+export default function QuoteSummaryModal({ ...props }: IQuoteSummaryModal) {
+ const { selectedItem, totalPrice } = useContext(ItemContext);
+ const { visible, setVisible } = useContext(QuoteSummaryModalContext);
+ const navigate = useNavigate();
+
+ const handleOkButton = () => {
+ setVisible(false);
+ navigate(PATH.result);
+ };
+
+ const optionNames = ['차량', '옵션', '들의', '임시', '목록', '목록입니다', '목록입니다'];
+ // const optionNames = selectedItem.options.map((option, idx) => {
+ // return option.name;
+ // });
+
+ return (
+
+ e.stopPropagation()}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 현재 총 가격
+ {totalPrice.toLocaleString()} 원
+
+
+
+
+
+ );
+}
+
+function Detail({ title, name, price }: { title: string; name: string; price: number }) {
+ return (
+
+ {title}
+ {name}
+ + {price.toLocaleString()}원
+
+ );
+}
+
+const QuoteModal = styled(WhiteModal)`
+ display: flex;
+ justify-content: space-between;
+ flex-direction: column;
+ width: 850px;
+ height: 520px;
+`;
+
+const OkButton = styled(RectButton)``;
+
+const Header = styled.div`
+ ${flexCenterCss}
+ height: 53px;
+`;
+const ModalTitle = styled.h1`
+ ${HeadingKrMedium5}
+`;
+const CloseButton = styled.button`
+ position: absolute;
+ right: 10px;
+`;
+const Row = styled.div`
+ ${flexCenterCss}
+ gap: 32px;
+ margin-bottom: 40px;
+`;
+const Body = styled.div`
+ padding: 24px 36px;
+`;
+const ImgSection = styled.div`
+ ${flexCenterCss}
+ width: 50%;
+ flex-direction: column;
+`;
+const CarImg = styled.img`
+ height: auto;
+`;
+const DetailSection = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 50%;
+ gap: 8px;
+`;
+
+const DetailWrapper = styled.div`
+ display: flex;
+ justify-content: space-between;
+ ${BodyKrRegular3}
+`;
+const DetailTitle = styled.div`
+ color: ${({ theme }) => theme.color.gray500};
+ text-align: start;
+ width: 100px;
+`;
+const DetailName = styled.div`
+ display: inline-block;
+ color: ${({ theme }) => theme.color.gray900};
+ text-align: start;
+ width: 210px;
+ overflow-x: scroll;
+ overflow-x: auto;
+ overflow-y: hidden;
+ white-space: nowrap;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+`;
+const DetailPrice = styled.div`
+ color: ${({ theme }) => theme.color.gray900};
+ text-align: end;
+ margin-left: auto;
+`;
+const PriceSection = styled.div`
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+`;
+const PriceCaption = styled.span`
+ ${BodyKrRegular4}
+ color: ${({ theme }) => theme.color.gray700};
+`;
+const Price = styled.span`
+ ${HeadingKrMedium2}
+ color: ${({ theme }) => theme.color.primaryColor};
+ margin-left: 16px;
+`;
+
+const Footer = styled.div``;
+
+const Hr = styled.div`
+ width: 100%;
+ height: 1px;
+ background-color: ${({ theme }) => theme.color.gray100};
+ margin: 7px 0;
+`;
diff --git a/frontend/src/components/modal/WhiteModal.tsx b/frontend/src/components/modal/WhiteModal.tsx
new file mode 100644
index 0000000..5c52819
--- /dev/null
+++ b/frontend/src/components/modal/WhiteModal.tsx
@@ -0,0 +1,18 @@
+import { HTMLAttributes } from 'react';
+import { styled } from 'styled-components';
+
+interface IWhiteModal extends HTMLAttributes {}
+
+export default function WhiteModal({ ...props }: IWhiteModal) {
+ return ;
+}
+
+const Wrapper = styled.div`
+ position: relative;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ overflow: hidden;
+ border-radius: 4px;
+ background-color: ${({ theme }) => theme.color.white};
+`;
diff --git a/frontend/src/components/summary/PriceSummary.tsx b/frontend/src/components/summary/PriceSummary.tsx
index 3762a72..30882cb 100644
--- a/frontend/src/components/summary/PriceSummary.tsx
+++ b/frontend/src/components/summary/PriceSummary.tsx
@@ -5,6 +5,7 @@ import { BodyKrRegular4, HeadingKrMedium2 } from '../../styles/typefaces';
import { useNavigate } from 'react-router-dom';
import { useContext } from 'react';
import { ItemContext } from '../../context/ItemProvider';
+import { QuoteSummaryModalContext } from '../../context/QuoteSummaryModalProvider';
interface IPriceSummary extends React.HTMLAttributes {
nextPagePath: string;
@@ -12,20 +13,25 @@ interface IPriceSummary extends React.HTMLAttributes {
export default function PriceSummary({ nextPagePath, ...props }: IPriceSummary) {
const { totalPrice } = useContext(ItemContext);
-
+ const { setVisible: setQuoteSummaryModalVisible } = useContext(QuoteSummaryModalContext);
const navigate = useNavigate();
- const handleButtonClick = () => {
+ const handleNextButtonClick = () => {
navigate(nextPagePath);
};
+ const handleSummaryButtonClick = () => {
+ setQuoteSummaryModalVisible(true);
+ };
return (
- 견적 요약
+
+ 견적 요약
+
현재 총 가격{totalPrice.toLocaleString()} 원
-
+
다음
diff --git a/frontend/src/containers/Modal/ModalContainer.tsx b/frontend/src/containers/Modal/ModalContainer.tsx
index 5261311..690e45f 100644
--- a/frontend/src/containers/Modal/ModalContainer.tsx
+++ b/frontend/src/containers/Modal/ModalContainer.tsx
@@ -5,17 +5,21 @@ import SimilarQuoteModal from '../../components/modal/SimilarQuoteModal';
import { GuideModalContext } from '../../context/GuideModalProvider';
import { SimilarQuoteModalContext } from '../../context/SimilarQuoteModalProvider';
import { CloseModalContext } from '../../context/CloseModalProvider';
+import QuoteSummaryModal from '../../components/modal/QuoteSummaryModal';
+import { QuoteSummaryModalContext } from '../../context/QuoteSummaryModalProvider';
export default function ModalContainer() {
const { setVisible: setCloseModalVisible } = useContext(CloseModalContext);
const { setVisible: setGuideModalVisible } = useContext(GuideModalContext);
const { setVisible: setSimilarQuoteModalVisible } = useContext(SimilarQuoteModalContext);
+ const { setVisible: setQuoteSummaryModalVisible } = useContext(QuoteSummaryModalContext);
return (
<>
setCloseModalVisible(false)} />
setGuideModalVisible(false)} />
setSimilarQuoteModalVisible(false)} />
+ setQuoteSummaryModalVisible(false)} />
>
);
}
diff --git a/frontend/src/containers/OuterColorPage/OuterColorBannerContainer.tsx b/frontend/src/containers/OuterColorPage/OuterColorBannerContainer.tsx
index 5ab83b9..1858dfc 100644
--- a/frontend/src/containers/OuterColorPage/OuterColorBannerContainer.tsx
+++ b/frontend/src/containers/OuterColorPage/OuterColorBannerContainer.tsx
@@ -3,17 +3,13 @@ import { styled } from 'styled-components';
import Banner from '../../components/common/banner/Banner';
import CenterWrapper from '../../components/layout/CenterWrapper';
import { flexCenterCss } from '../../utils/commonStyle';
-import { useFetch } from '../../hooks/useFetch';
-import { IMG_URL, OUTER_IMG_API } from '../../utils/apis';
+import { IMG_URL } from '../../utils/apis';
import Loading from '../../components/loading/Loading';
import { OuterColorContext } from '../../context/OuterColorProvider';
import car360Reducer from '../../reducer/car360Reducer';
export default function OuterColorBannerContainer() {
- const { seletedColorId } = useContext(OuterColorContext);
- const { data: car360ImgUrls, loading } = useFetch(
- `${OUTER_IMG_API}?colorid=${seletedColorId}`
- );
+ const { car360UrlsData } = useContext(OuterColorContext);
const [imgState, setImgState] = useReducer(car360Reducer, {
visibleIdx: 0,
isDragging: false,
@@ -21,14 +17,13 @@ export default function OuterColorBannerContainer() {
startIdx: 0,
imgLoading: true,
});
- const imgLen = car360ImgUrls ? car360ImgUrls.length : 0;
+ const imgLen = car360UrlsData ? car360UrlsData.length : 0;
const handleMousedown: MouseEventHandler = useCallback(
({ pageX }) => {
setImgState({ type: 'SET_IS_DRAGGING', value: true });
setImgState({ type: 'SET_START_X', value: pageX });
setImgState({ type: 'SET_START_IDX', value: imgState.visibleIdx });
- console.log(imgState.visibleIdx);
},
[imgState]
);
@@ -67,22 +62,22 @@ export default function OuterColorBannerContainer() {
}, []);
const downloadAndSaveImages = useCallback(
- async (car360ImgUrls: string[], abortController: AbortController) => {
- if (isLoaded(car360ImgUrls)) {
+ async (car360UrlsData: string[], abortController: AbortController) => {
+ if (isLoaded(car360UrlsData)) {
setImgState({ type: 'SET_IMG_LOADING', value: false });
return;
}
setImgState({ type: 'SET_IMG_LOADING', value: true });
await Promise.all(
- car360ImgUrls.map(async (url, idx) => {
+ car360UrlsData.map(async (url, idx) => {
const isImageExist = localStorage.getItem(url) !== null;
if (isImageExist) return;
const res = await fetch(IMG_URL + url, {
signal: abortController.signal,
});
const imgBlob = await res.blob();
- const localStorageKey = car360ImgUrls[idx];
+ const localStorageKey = car360UrlsData[idx];
localStorage.setItem(localStorageKey, URL.createObjectURL(imgBlob));
return imgBlob;
})
@@ -93,15 +88,15 @@ export default function OuterColorBannerContainer() {
);
useEffect(() => {
- if (!car360ImgUrls || loading) return;
+ if (!car360UrlsData) return;
const abortController = new AbortController();
- downloadAndSaveImages(car360ImgUrls, abortController);
+ downloadAndSaveImages(car360UrlsData, abortController);
return () => {
abortController.abort();
};
- }, [downloadAndSaveImages, loading, car360ImgUrls]);
+ }, [downloadAndSaveImages, car360UrlsData]);
- const car360Components = car360ImgUrls?.map((url, idx) => {
+ const car360Components = car360UrlsData?.map((url, idx) => {
const imgSrc = localStorage.getItem(url);
if (!imgSrc) return;
return ;
diff --git a/frontend/src/containers/OuterColorPage/OuterColorSelectContainer.tsx b/frontend/src/containers/OuterColorPage/OuterColorSelectContainer.tsx
index f6e16c0..34bbca0 100644
--- a/frontend/src/containers/OuterColorPage/OuterColorSelectContainer.tsx
+++ b/frontend/src/containers/OuterColorPage/OuterColorSelectContainer.tsx
@@ -9,12 +9,8 @@ import { IOuterColor, ISelected, OuterColorContext } from '../../context/OuterCo
import { ItemContext } from '../../context/ItemProvider';
export default function OuterColorSelectContainer() {
- const {
- data: outerColorData,
- selectedIdx,
- setSelectedIdx,
- setSelectedColorId,
- } = useContext(OuterColorContext);
+ const { outerColorData, selectedIdx, setSelectedIdx, setSelectedColorId } =
+ useContext(OuterColorContext);
const [cardPageList, setCardPageList] = useState();
const { totalPrice, setSelectedItem, setTotalPrice } = useContext(ItemContext);
const prevTotalPrice = useRef(totalPrice);
@@ -31,6 +27,7 @@ export default function OuterColorSelectContainer() {
id: selectedItem.colorId,
name: selectedItem.colorName,
imgSrc: selectedItem.colorImage,
+ carImgSrc: '',
price: selectedItem.colorPrice,
title: '외장 색상',
},
diff --git a/frontend/src/containers/ResultPage/DetailContainer.tsx b/frontend/src/containers/ResultPage/DetailContainer.tsx
index 26de4f0..74f1e19 100644
--- a/frontend/src/containers/ResultPage/DetailContainer.tsx
+++ b/frontend/src/containers/ResultPage/DetailContainer.tsx
@@ -2,9 +2,16 @@ import { styled } from 'styled-components';
import { HeadingKrMedium7 } from '../../styles/typefaces';
import Details from '../../components/details/Details';
import SummaryItem from '../../components/details/SummaryItem';
-import { useState } from 'react';
+import { useContext, useEffect, useState } from 'react';
+import { ItemContext } from '../../context/ItemProvider';
export default function DetailContainer() {
+ const { selectedItem } = useContext(ItemContext);
+ const [detailPrice, setDetailPrice] = useState({
+ modelTypePrice: 0,
+ colorPrice: 0,
+ optionPrice: 0,
+ });
const [isOpen, setIsOepn] = useState<{ [key: number]: boolean }>({
1: true,
2: true,
@@ -24,185 +31,112 @@ export default function DetailContainer() {
});
};
+ useEffect(() => {
+ const modelTypePrice =
+ selectedItem.modelType.powerTrain.price +
+ selectedItem.modelType.bodyType.price +
+ selectedItem.modelType.operation.price;
+ const colorPrice = selectedItem.innerColor.price + selectedItem.outerColor.price;
+ const optionPrice = selectedItem.options.reduce((acc, option) => acc + option.price, 0);
+
+ setDetailPrice({
+ modelTypePrice,
+ colorPrice,
+ optionPrice,
+ });
+ }, [selectedItem]);
+
+ const optionSummaryItems = selectedItem.options.map((option, idx) => {
+ return (
+
+ );
+ });
+
return (
상세 견적
- setOpenedIdx(1)}>
+ setOpenedIdx(1)}
+ >
- setOpenedIdx(2)}>
+ setOpenedIdx(2)}
+ >
-
-
-
-
- setOpenedIdx(3)}>
-
-
-
-
-
- setOpenedIdx(4)}>
-
-
-
-
- setOpenedIdx(5)}>
-
-
-
-
-
-
- setOpenedIdx(6)}>
-
-
-
-
-
-
- setOpenedIdx(7)}>
-
-
-
-
-
-
- setOpenedIdx(8)}>
-
-
-
-
-
+ setOpenedIdx(3)}
+ >
+ {optionSummaryItems}
+ setOpenedIdx(4)}>
+ setOpenedIdx(5)}
+ >
+ setOpenedIdx(6)}
+ >
+ setOpenedIdx(7)}
+ >
+ setOpenedIdx(8)}>
);
}
diff --git a/frontend/src/containers/ResultPage/ResultFooterContainer.tsx b/frontend/src/containers/ResultPage/ResultFooterContainer.tsx
index f6d98a1..82a841a 100644
--- a/frontend/src/containers/ResultPage/ResultFooterContainer.tsx
+++ b/frontend/src/containers/ResultPage/ResultFooterContainer.tsx
@@ -2,13 +2,17 @@ import { styled } from 'styled-components';
import CenterWrapper from '../../components/layout/CenterWrapper';
import { BodyKrRegular3, HeadingKrMedium2 } from '../../styles/typefaces';
import RectButton from '../../components/common/buttons/RectButton';
+import { useContext } from 'react';
+import { ItemContext } from '../../context/ItemProvider';
export default function ResultFooterContainer() {
+ const { totalPrice } = useContext(ItemContext);
+
return (
최종 견적 가격
- 100원
+ {totalPrice.toLocaleString()} 원
공유하기
diff --git a/frontend/src/context/ItemProvider.tsx b/frontend/src/context/ItemProvider.tsx
index 95eb0e8..fee622f 100644
--- a/frontend/src/context/ItemProvider.tsx
+++ b/frontend/src/context/ItemProvider.tsx
@@ -9,6 +9,9 @@ interface detailItemType extends defaultItemType {
title: string;
imgSrc: string;
}
+interface IOuterColorItemType extends detailItemType {
+ carImgSrc: string;
+}
interface ISelectedItem {
trim: defaultItemType;
modelType: {
@@ -17,7 +20,7 @@ interface ISelectedItem {
operation: detailItemType;
};
innerColor: detailItemType;
- outerColor: detailItemType;
+ outerColor: IOuterColorItemType;
options: detailItemType[];
}
@@ -73,6 +76,7 @@ const initialSelectedItem = {
name: '',
title: '',
imgSrc: '',
+ carImgSrc: '',
price: 0,
},
options: [{ id: 0, name: '', title: '', imgSrc: '', price: 0 }],
@@ -91,7 +95,7 @@ type actionType =
| { type: 'SET_OPERATION'; value: detailItemType }
| { type: 'SET_BODY_TYPE'; value: detailItemType }
| { type: 'SET_INNER_COLOR'; value: detailItemType }
- | { type: 'SET_OUTER_COLOR'; value: detailItemType }
+ | { type: 'SET_OUTER_COLOR'; value: IOuterColorItemType }
| { type: 'SET_OPTIONS'; value: detailItemType[] };
const reducer = (state: ISelectedItem, action: actionType): ISelectedItem => {
diff --git a/frontend/src/context/OuterColorProvider.tsx b/frontend/src/context/OuterColorProvider.tsx
index 780834f..1a8b21e 100644
--- a/frontend/src/context/OuterColorProvider.tsx
+++ b/frontend/src/context/OuterColorProvider.tsx
@@ -16,42 +16,53 @@ export interface ISelected {
}
interface IOuterColorContext {
- data: IOuterColor[] | null;
+ outerColorData: IOuterColor[] | null;
+ car360UrlsData: string[] | null;
loading: boolean;
selectedIdx: ISelected;
seletedColorId: number;
- setData: Dispatch>;
+ setOuterColorData: Dispatch>;
setLoading: Dispatch>;
setSelectedIdx: Dispatch>;
setSelectedColorId: Dispatch>;
+ setCar360UrlsData: Dispatch>;
}
const initialContext: IOuterColorContext = {
- data: null,
+ outerColorData: null,
+ car360UrlsData: [],
loading: true,
selectedIdx: { page: 0, idx: 0 },
seletedColorId: 3,
setLoading: () => {},
- setData: () => {},
+ setOuterColorData: () => {},
setSelectedIdx: () => {},
setSelectedColorId: () => {},
+ setCar360UrlsData: () => {},
};
export const OuterColorContext = createContext(initialContext);
export default function OuterColorProvider({ children }: IOuterColorProvider) {
- const [data, setData] = useState(initialContext.data);
+ const [outerColorData, setOuterColorData] = useState(
+ initialContext.outerColorData
+ );
+ const [car360UrlsData, setCar360UrlsData] = useState(
+ initialContext.car360UrlsData
+ );
const [selectedIdx, setSelectedIdx] = useState(initialContext.selectedIdx);
const [seletedColorId, setSelectedColorId] = useState(initialContext.seletedColorId);
const [loading, setLoading] = useState(initialContext.loading);
const providerValue = {
- data,
+ outerColorData,
+ car360UrlsData,
selectedIdx,
loading,
seletedColorId,
setSelectedIdx,
- setData,
+ setOuterColorData,
+ setCar360UrlsData,
setLoading,
setSelectedColorId,
};
diff --git a/frontend/src/context/QuoteSummaryModalProvider.tsx b/frontend/src/context/QuoteSummaryModalProvider.tsx
new file mode 100644
index 0000000..36fb268
--- /dev/null
+++ b/frontend/src/context/QuoteSummaryModalProvider.tsx
@@ -0,0 +1,27 @@
+import { ReactNode, createContext, useState } from 'react';
+
+interface IQuoteSummaryModalContext {
+ visible: boolean;
+ setVisible: React.Dispatch>;
+}
+
+interface IQuoteSummaryModalProvider {
+ children: ReactNode;
+}
+
+const initialContext = {
+ visible: false,
+ setVisible: () => {},
+};
+
+export const QuoteSummaryModalContext = createContext(initialContext);
+
+export default function QuoteSummaryModalProvider({ children }: IQuoteSummaryModalProvider) {
+ const [visible, setVisible] = useState(initialContext.visible);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/frontend/src/pages/OuterColorPage.tsx b/frontend/src/pages/OuterColorPage.tsx
index eb5b13c..55f048a 100644
--- a/frontend/src/pages/OuterColorPage.tsx
+++ b/frontend/src/pages/OuterColorPage.tsx
@@ -1,18 +1,21 @@
+import { useContext, useEffect } from 'react';
import OuterColorSelectContainer from '../containers/OuterColorPage/OuterColorSelectContainer';
import OuterColorBannerContainer from '../containers/OuterColorPage/OuterColorBannerContainer';
-import { useFetch } from '../hooks/useFetch';
-import { OUTER_COLOR_API } from '../utils/apis';
-import { useContext, useEffect } from 'react';
import { IOuterColor, OuterColorContext } from '../context/OuterColorProvider';
+import { useFetch } from '../hooks/useFetch';
+import { OUTER_COLOR_API, OUTER_IMG_API } from '../utils/apis';
export default function OuterColorPage() {
- const { data, loading } = useFetch(`${OUTER_COLOR_API}?carid=${1}`); // Todo. selectedItem.trim.id로 바꾸기
- const { setData, setLoading } = useContext(OuterColorContext);
+ const { seletedColorId, setOuterColorData, setCar360UrlsData } = useContext(OuterColorContext);
+ const { data: outerColorData } = useFetch(`${OUTER_COLOR_API}?carid=${1}`); // Todo. selectedItem.trim.id로 바꾸기
+ const { data: car360ImgUrls } = useFetch(`${OUTER_IMG_API}?colorid=${seletedColorId}`);
useEffect(() => {
- setData(data);
- setLoading(loading);
- }, [data, loading, setData, setLoading]);
+ setOuterColorData(outerColorData);
+ }, [outerColorData, setOuterColorData]);
+ useEffect(() => {
+ setCar360UrlsData(car360ImgUrls);
+ }, [car360ImgUrls, setCar360UrlsData]);
return (
<>
From 170ddc383decb2d02e745533e405a1b4a5e93c89 Mon Sep 17 00:00:00 2001
From: jijiseong
Date: Sat, 19 Aug 2023 14:24:19 +0900
Subject: [PATCH 3/7] =?UTF-8?q?[REFACTOR]=20#316:=20=EC=98=B5=EC=85=98=20?=
=?UTF-8?q?=EC=B4=88=EA=B8=B0=EA=B0=92=20=EB=B9=88=EA=B0=92=EC=9C=BC?=
=?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20=EC=98=A4=ED=83=80=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../components/modal/QuoteSummaryModal.tsx | 25 ++++++++++++-------
frontend/src/context/ItemProvider.tsx | 2 +-
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/frontend/src/components/modal/QuoteSummaryModal.tsx b/frontend/src/components/modal/QuoteSummaryModal.tsx
index d201d7a..2e1affa 100644
--- a/frontend/src/components/modal/QuoteSummaryModal.tsx
+++ b/frontend/src/components/modal/QuoteSummaryModal.tsx
@@ -18,16 +18,23 @@ import { DimmedBackground } from './DimmedBackground';
import WhiteModal from './WhiteModal';
interface IQuoteSummaryModal extends HTMLAttributes {}
-
+interface IDetail {
+ title: string;
+ name: string;
+ price: number;
+}
export default function QuoteSummaryModal({ ...props }: IQuoteSummaryModal) {
const { selectedItem, totalPrice } = useContext(ItemContext);
const { visible, setVisible } = useContext(QuoteSummaryModalContext);
const navigate = useNavigate();
- const handleOkButton = () => {
+ const handleOkButtonClick = () => {
setVisible(false);
navigate(PATH.result);
};
+ const handleCloseButtonClicke = () => {
+ setVisible(false);
+ };
const optionNames = ['차량', '옵션', '들의', '임시', '목록', '목록입니다', '목록입니다'];
// const optionNames = selectedItem.options.map((option, idx) => {
@@ -39,7 +46,7 @@ export default function QuoteSummaryModal({ ...props }: IQuoteSummaryModal) {
e.stopPropagation()}>
@@ -93,7 +100,7 @@ export default function QuoteSummaryModal({ ...props }: IQuoteSummaryModal) {