Skip to content

Commit

Permalink
Merge pull request #30 from 8princesses/feat/detail
Browse files Browse the repository at this point in the history
Feat/detail
  • Loading branch information
leeks9653 authored Oct 22, 2023
2 parents 3867571 + 6a45632 commit a200e9b
Show file tree
Hide file tree
Showing 27 changed files with 794 additions and 130 deletions.
2 changes: 1 addition & 1 deletion .env.development
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
NEXT_PUBLIC_API_URL=https://api.modumozu.com/
NEXT_PUBLIC_KAKAO_KEY="5d83cd0432c767f46c20dceb0f8f3947"
NEXT_PUBLIC_KAKAO_KEY="5d83cd0432c767f46c20dceb0f8f3947"
2 changes: 1 addition & 1 deletion .env.production
Original file line number Diff line number Diff line change
@@ -1 +1 @@
NEXT_PUBLIC_API_URL=https://api.modumozu.com/
NEXT_PUBLIC_API_URL=https://api.modumozu.com/
34 changes: 29 additions & 5 deletions src/api/ipo.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
import { EndedStockType, UpcomingStockType } from "@/types";
import instance from "./common";
import api from "./common";
import { IPODetailResponse } from "@/dto/detail";
import { ApiResponse } from "./network";
import { NewsResponse } from "@/dto/news";

const url = "/api/ipo/v1";

/**
* IPO 상세 조회
*/
export const getDetailById = async (id: string) => {
const data = await instance.get(`${url}/${id}`);
console.log("data", data);
const {
data: { data },
} = await api.get<ApiResponse<IPODetailResponse>>(`${url}/ipo/${id}`);

return data;
};

/**
* IPO 상세 news
*/
export const getDetailNewsById = async (id: string) => {
const {
data: { data },
} = await api.get<ApiResponse<NewsResponse>>(`${url}/ipo/${id}/news`);

return data.news;
};

/**
* 관심 공모주 수정
*/
export const updateDetailPin = async (ipoId: number) => {
await api.put(`${url}/ipo/pin`, { ipoId });
};

/**
* 다가오는 공모주 조회
*/
export const fetchUpcomingStocks = async (): Promise<UpcomingStockType> => {
const { data } = await instance.get(url + "/ipo");
const { data } = await api.get(url + "/ipo");
return data.data;
};

/**
* 종료된 공모주 조회
*/
export const fetchEndedStocks = async (page: number): Promise<EndedStockType[]> => {
const { data } = await instance.get(`${url}/closed-ipo?page=${page}&size=10`);
const { data } = await api.get(`${url}/closed-ipo?page=${page}&size=10`);
return data.data.ipos;
};
6 changes: 6 additions & 0 deletions src/api/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class ModuMozuError {}

export interface ApiResponse<T> {
data: T;
timestamp: number;
}
106 changes: 74 additions & 32 deletions src/app/detail/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import Modal from "@/components/common/Modal";
import { getDetailById, getDetailNewsById } from "@/api/ipo";
import DetailBottomButton from "@/components/detail/DetailBottomButton";
import DetailCard from "@/components/detail/DetailCard";
import DetailHeader from "@/components/detail/DetailHeader";
import DetailTitle from "@/components/detail/DetailTitle";
Expand All @@ -9,52 +10,93 @@ import IPOInfo from "@/components/detail/IPOInfo";
import IPOTapMenu from "@/components/detail/IPOTapMenu";
import InvestCompetition from "@/components/detail/InvestCompetition";
import POInfo from "@/components/detail/POInfo";
import queryKeys from "@/constants/queryKeys";
import { useQuery } from "@tanstack/react-query";
import { NextPage } from "next";

const ipoConfirmDummy: IPOComfirmTableData = [
{
label: "15일",
value: "22,886,000",
},
{
label: "1개월",
value: "22,886,000",
},
{
label: "3개월",
value: "22,886,000",
},
{
label: "6개월",
value: "22,886,000",
},
{ label: "미확약", value: "2,808,389,000" },
{ label: "합계", value: "3,033,263,000" },
{ label: "총 수량 대비 비율 (%)", value: "11%" },
];
interface DetailProps {
params: { id: string };
}

const Detail = () => {
const Detail: NextPage<DetailProps> = ({ params }) => {
const id = params.id;

const { data, isLoading } = useQuery(queryKeys.DETAIL, () => {
return getDetailById(id);
});
const { data: news = [], isLoading: isNewsLoading } = useQuery(queryKeys.NEWS, () => {
return getDetailNewsById(id);
});
const buildMandatoryHoldingCommitmentRate = (): IPOComfirmTableData => {
if (data) {
return [
{ label: "15일", value: data.subscriptionAmountByPeriod15Days },
{ label: "1개월", value: data.subscriptionAmountByPeriod30Days },
{ label: "3개월", value: data.subscriptionAmountByPeriod90Days },
{ label: "6개월", value: data.subscriptionAmountByPeriod180Days },
{ label: "미확약", value: data.subscriptionAmountByPeriodByNone },
{ label: "합계", value: data.subscriptionAmountByTotal },
{ label: "총 수량 대비 비율 (%)", value: `${data.mandatoryHoldingCommitmentRate}%` },
];
}
return [];
};

if (data === undefined || isLoading) {
return null;
}
return (
<div>
<DetailHeader />
<DetailTitle date="18" name="큐리옥스바이오시스템즈" category="내구 소비재 및 의류" />
<>
<DetailHeader id={data.id} pinned={data.pinned} />
<DetailTitle
name={data.name}
category={data.category}
status={data.status}
offerBeginAt={data.offerBeginAt}
offerEndAt={data.offerEndAt}
listingAt={data.listingAt}
/>
<DetailCard.wrapper>
<DetailCard.item>
<IPOInfo />
<IPOInfo
nonRemainAgents={data.nonRemainAgents}
remainAgents={data.remainAgents}
publicOfferingTotalPrice={data.publicOfferingTotalPrice}
subscriptionDepositRate={data.subscriptionDepositRate}
investorCompetitionRate={data.investorCompetitionRate}
mandatoryHoldingCommitmentRate={data.mandatoryHoldingCommitmentRate}
/>
</DetailCard.item>
<DetailCard.item>
<IPOTapMenu />
<IPOTapMenu
news={news}
demandForecastBeginAt={data.demandForecastBeginAt}
refundAt={data.refundAt}
listingAt={data.listingAt}
offerBeginAt={data.offerBeginAt}
offerEndAt={data.offerEndAt}
/>
</DetailCard.item>
<DetailCard.item>
<POInfo />
<POInfo
fixedOfferPrice={data.fixedOfferPrice || data.minDesiredOfferPrice}
publicOfferingTotalPrice={data.publicOfferingTotalPrice}
publicOfferingAmount={data.publicOfferingAmount}
subscriptionDepositRate={data.subscriptionDepositRate}
/>
</DetailCard.item>
<DetailCard.item>
<InvestCompetition />
<InvestCompetition investorCompetitionRate={data.investorCompetitionRate} />
</DetailCard.item>
<DetailCard.item>
<IPOConfirm data={ipoConfirmDummy} />
<IPOConfirm
mandatoryHoldingCommitmentRate={data.mandatoryHoldingCommitmentRate}
data={buildMandatoryHoldingCommitmentRate()}
/>
<DetailBottomButton proposal={data.proposal} offerBeginAt={data.offerBeginAt} offerEndAt={data.offerEndAt} />
</DetailCard.item>
</DetailCard.wrapper>
</div>
</>
);
};

Expand Down
17 changes: 17 additions & 0 deletions src/app/enterprise/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import PageHeader from "@/components/common/PageHeader";
import { FC, ReactNode } from "react";

interface EnterPriseLayoutProps {
children: ReactNode;
}

const EnterPriseLayout: FC<EnterPriseLayoutProps> = ({ children }) => {
return (
<div style={{ backgroundColor: "white" }}>
<PageHeader />
{children}
</div>
);
};

export default EnterPriseLayout;
16 changes: 16 additions & 0 deletions src/app/enterprise/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use client";

import DetailCard from "@/components/detail/DetailCard";

const EnterPrise = () => {
return (
<>
<DetailCard.wrapper>
<DetailCard.item>하ㅓ이</DetailCard.item>
<DetailCard.item>힝;</DetailCard.item>
</DetailCard.wrapper>
</>
);
};

export default EnterPrise;
4 changes: 4 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ video {
box-sizing: border-box;
}

a {
text-decoration: none;
}

article,
aside,
details,
Expand Down
6 changes: 6 additions & 0 deletions src/app/test/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use client";

const Test = () => {
return <div></div>;
};
export default Test;
42 changes: 42 additions & 0 deletions src/components/common/PageHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";

import BackIcon from "@/svg/BackIcon";
import { useRouter } from "next/navigation";
import { FC, ReactNode } from "react";
import styled from "styled-components";

interface PageHeaderProps {
showPrevButton?: boolean;
addtionalButton?: ReactNode;
}

const PageHeader: FC<PageHeaderProps> = ({ showPrevButton = true, addtionalButton }) => {
const router = useRouter();

const handlePrevClick = () => {
router.back();
};

return (
<Header>
{showPrevButton && (
<div>
<BackButton onClick={handlePrevClick} />
</div>
)}

{addtionalButton && <div>{addtionalButton}</div>}
</Header>
);
};
export default PageHeader;

const Header = styled.header`
display: flex;
justify-content: space-between;
padding: 16px;
`;

const BackButton = styled(BackIcon)`
cursor: pointer;
`;
24 changes: 24 additions & 0 deletions src/components/detail/DetailBottomButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import styled from "styled-components";
import Button from "../common/Button";
import { Proposal } from "@/dto/detail";
import { FC } from "react";

interface DetailBottomButton {
proposal: Proposal;
offerBeginAt: string;
offerEndAt: string;
}

const DetailBottomButton: FC<DetailBottomButton> = ({ proposal, offerBeginAt, offerEndAt }) => {
return (
<BottomButtonWrap>
<Button width="100%">버튼이요</Button>
</BottomButtonWrap>
);
};

export default DetailBottomButton;

const BottomButtonWrap = styled.div`
padding: 16px 16px 20px 16px;
`;
Loading

0 comments on commit a200e9b

Please sign in to comment.