Skip to content

Commit

Permalink
Refactor/64: 로딩/에러 처리 (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
cindycho0423 authored Dec 9, 2024
1 parent 4883c5d commit 41c744b
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 82 deletions.
Binary file added public/images/login-guard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/shield.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion src/api/transaction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,20 @@ export async function cancelTrade({
}
}

export interface TradeHistory {
id: number;
buyPrice: number;
remainCount: number;
stockCount: number;
stockName: string;
buyOrder: string;
}

// 매수/매도 체결내역
export async function getTradeHistory(
token: string | null,
stockName: string,
): Promise<OrderHistory[]> {
): Promise<TradeHistory[]> {
if (token === null) {
throw new Error();
}
Expand Down
9 changes: 7 additions & 2 deletions src/app/search/[id]/_components/loading-spiner.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
export default function LoadingSpinner() {
import cn from "@/utils/cn";

interface LoadingSpinnerProps {
className?: string;
}
export default function LoadingSpinner({ className }: LoadingSpinnerProps) {
return (
<div className="flex h-64 items-center justify-center">
<div className={cn("flex h-64 items-center justify-center", className)}>
<div className="loadingSpinner" />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { OrderHistory } from "@/api/transaction";
import CheckButton from "@/components/common/check-button";
import cn from "@/utils/cn";
import { getKoreanPrice } from "@/utils/price";

interface EditTableBodyProps {
Expand All @@ -26,7 +27,15 @@ export default function EditTableBody({
</td>
<td className=" py-10 pl-20 text-left">
<div className="pb-6 text-12-400">
<span className="pr-3 text-[#F20000]">{data.type} 정정</span>
<span
className={cn(
"pr-3",
data.type === "매수" && "text-[#F20000]",
data.type === "매도" && "text-[#4882FA]",
)}
>
{data.type} 정정
</span>
<span className="text-[#9B9B9B]">{data.OrderId}</span>
</div>
{data.stockName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useStockInfoContext } from "@/context/stock-info-context";
import { useAuth } from "@/hooks/use-auth";
import { useToast } from "@/store/use-toast-store";

import LoadingSpinner from "../../loading-spiner";
import Trade from "../trade";
import TransactionTable from "../transaction-table";
import EditTableBody from "./edit-table-body";
Expand All @@ -21,7 +22,11 @@ export default function EditCancel() {
const { showToast } = useToast();
const queryClient = useQueryClient();

const { data: limitOrderData } = useQuery({
const {
data: limitOrderData,
isLoading,
isPending,
} = useQuery({
queryKey: ["limitOrder"],
queryFn: () => getTrade(token, stockName),
enabled: !!isAuthenticated && !!token,
Expand Down Expand Up @@ -65,6 +70,9 @@ export default function EditCancel() {
onSettled: () => {
setIsCancelTable(false);
},
onError: (error) => {
showToast(error.message, "error");
},
});

const { mutate: modifyTradeMutate } = useMutation({
Expand All @@ -77,6 +85,9 @@ export default function EditCancel() {
setIsEditForm(false);
setSelectedOrders([]);
},
onError: (error) => {
showToast(error.message, "error");
},
});

const handleCancelConfirm = (orderId: string) => {
Expand All @@ -90,6 +101,10 @@ export default function EditCancel() {
);
}

if (isLoading || isPending) {
return <LoadingSpinner className="mt-230" />;
}

if (isCancelTable) {
return (
<>
Expand Down Expand Up @@ -125,17 +140,19 @@ export default function EditCancel() {
<table className="w-full text-center text-14-500">
<EditTableHeader />
{limitOrderData && limitOrderData.length > 0 ? (
limitOrderData.map((data) => (
<EditTableBody
key={data.OrderId}
data={data}
isChecked={selectedOrders.includes(data.OrderId.toString())}
toggleSelection={toggleOrderSelection}
/>
))
[...limitOrderData]
.sort((a, b) => b.OrderId - a.OrderId)
.map((data) => (
<EditTableBody
key={data.OrderId}
data={data}
isChecked={selectedOrders.includes(data.OrderId.toString())}
toggleSelection={toggleOrderSelection}
/>
))
) : (
<tr>
<td colSpan={5} className="py-20 text-center text-gray-500">
<td colSpan={5} className="py-20 text-center text-16-500">
<Image
src="/images/green-wallet.png"
width={150}
Expand All @@ -149,18 +166,20 @@ export default function EditCancel() {
)}
</table>
</div>
<div className="mt-20 text-center">
<Button
variant="red"
className="mr-10 w-120 bg-[#1DA65A] hover:bg-[#1DA65A]/95"
onClick={handleEdit}
>
정정
</Button>
<Button variant="red" className="w-120" onClick={handleCancel}>
취소
</Button>
</div>
{limitOrderData && limitOrderData.length > 0 && (
<div className="mt-20 text-center">
<Button
variant="red"
className="mr-10 w-120 text-black bg-[#0FED78] hover:bg-[#0FED78]/95"
onClick={handleEdit}
>
정정
</Button>
<Button variant="red" className="w-120" onClick={handleCancel}>
취소
</Button>
</div>
)}
</>
);
}
55 changes: 39 additions & 16 deletions src/app/search/[id]/_components/transaction-form/history.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,63 @@
import { useQuery } from "@tanstack/react-query";
import Image from "next/image";

import { getTradeHistory } from "@/api/transaction";
import { useStockInfoContext } from "@/context/stock-info-context";
import { useAuth } from "@/hooks/use-auth";

import LoadingSpinner from "../loading-spiner";
import TransactionTable from "./transaction-table";

export default function History() {
const { token, isAuthenticated } = useAuth();
const { stockName } = useStockInfoContext();

const { data: tradeHistoryData } = useQuery({
const {
data: tradeHistoryData,
isLoading,
isPending,
} = useQuery({
queryKey: ["tradeHistory"],
queryFn: () => getTradeHistory(token, stockName),
enabled: !!isAuthenticated && !!token,
});

if (isLoading || isPending) {
return <LoadingSpinner className="mt-230" />;
}

return (
<div className="flex h-470 flex-col gap-20 overflow-auto">
{tradeHistoryData && tradeHistoryData?.length > 0 ? (
tradeHistoryData.map((history) => (
<TransactionTable
key={history.OrderId}
color="green"
isSubmit={false}
submittedData={{
stockName: history.stockName,
count: history.stockCount,
bidding: history.buyPrice,
totalAmount: history.buyPrice * history.stockCount,
buyOrder: history.type,
}}
/>
))
[...tradeHistoryData]
.sort((a, b) => b.id - a.id)
.map((history) => (
<TransactionTable
key={history.id}
color={history.buyOrder === "매수" ? "red" : "blue"}
isSubmit={false}
submittedData={{
stockName: history.stockName,
count: history.stockCount,
bidding: history.buyPrice,
totalAmount: history.buyPrice * history.stockCount,
buyOrder: history.buyOrder,
}}
/>
))
) : (
<div>체결내역이 없습니다. 거래를 시작해보세요!</div>
<div className="py-20 text-center font-medium leading-5">
<Image
src="/images/green-wallet.png"
width={150}
height={150}
className="mx-auto mb-30 mt-65"
alt="지갑 그림"
/>
체결내역이 없습니다.
<br />
거래를 시작해보세요!
</div>
)}
</div>
);
Expand Down
104 changes: 72 additions & 32 deletions src/app/search/[id]/_components/transaction-form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
"use client";

import Image from "next/image";
import Link from "next/link";

import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/common/tabs";
import { StockInfoProvider } from "@/context/stock-info-context";
import { useAuth } from "@/hooks/use-auth";

import { StockInfo } from "../../types";
import LoadingSpinner from "../loading-spiner";
import EditCancel from "./edit-cancel";
import History from "./history";
import Trade from "./trade";
Expand All @@ -22,41 +27,76 @@ export default function TransactionForm({
stockName,
stockInfo,
}: TransactionFormProps) {
const { isAuthenticated, isInitialized } = useAuth();

if (!isInitialized) {
return (
<div className="ml-17 h-630 min-w-450 rounded-10 bg-white px-22 py-30">
<h3 className="mb-250 text-20-700">거래하기</h3>
<LoadingSpinner />
</div>
);
}

return (
<div className="ml-17 h-630 min-w-450 rounded-10 bg-white px-22 py-30">
<h3 className="mb-16 text-20-700">거래하기</h3>
<StockInfoProvider
value={{
stockName,
stockInfo,
}}
>
<Tabs defaultValue="buy">
<TabsList>
<TabsTrigger value="buy" buttonColor="red">
매수
</TabsTrigger>
<TabsTrigger value="sell" buttonColor="blue">
매도
</TabsTrigger>
<TabsTrigger value="history">체결내역</TabsTrigger>
<TabsTrigger value="edit-cancel">정정 / 취소</TabsTrigger>
</TabsList>

<TabsContent value="buy">
<Trade type="buy" />
</TabsContent>
<TabsContent value="sell">
<Trade type="sell" />
</TabsContent>
<TabsContent value="history">
<History />
</TabsContent>
<TabsContent value="edit-cancel">
<EditCancel />
</TabsContent>
</Tabs>
</StockInfoProvider>
{isAuthenticated ? (
<StockInfoProvider
value={{
stockName,
stockInfo,
}}
>
<Tabs defaultValue="buy">
<TabsList>
<TabsTrigger value="buy" buttonColor="red">
매수
</TabsTrigger>
<TabsTrigger value="sell" buttonColor="blue">
매도
</TabsTrigger>
<TabsTrigger value="history">체결내역</TabsTrigger>
<TabsTrigger value="edit-cancel">정정 / 취소</TabsTrigger>
</TabsList>
<TabsContent value="buy">
<Trade type="buy" />
</TabsContent>
<TabsContent value="sell">
<Trade type="sell" />
</TabsContent>
<TabsContent value="history">
<History />
</TabsContent>
<TabsContent value="edit-cancel">
<EditCancel />
</TabsContent>
</Tabs>
</StockInfoProvider>
) : (
<div className="relative">
<Image
src="/images/login-guard.png"
alt="보안 아이콘"
width={300}
height={300}
className="absolute right-1/2 top-40 translate-x-1/2"
/>
<div className="relative top-250 w-full text-center leading-8">
<span className="text-20-700">로그인이 필요해요!</span>
<br />
<span className="text-16-500 text-gray-500">
가상 거래를 하기 위해서는 로그인이 필수적이에요!
</span>
<Link
href="/login"
className="m-auto mt-40 block w-150 rounded-4 bg-[#11E977] py-16 text-center text-16-700"
>
로그인 하기
</Link>
</div>
</div>
)}
</div>
);
}
Loading

0 comments on commit 41c744b

Please sign in to comment.