Skip to content

Commit 6af5d27

Browse files
committed
fix: 코드 래빗 반영
1 parent 41e3e6a commit 6af5d27

File tree

8 files changed

+110
-37
lines changed

8 files changed

+110
-37
lines changed

src/app/orders/[orderId]/cancel/_components/cancel-form.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
OrderRefundInfoResponse,
1010
OrderSummary,
1111
} from '@/types/domain/order';
12-
import { OrderListCard } from '@/components/orders/order-list-card';
12+
import OrderListCard from '@/components/orders/order-list-card';
1313
import Image from 'next/image';
1414

1515
const CANCEL_REASONS = [
@@ -46,6 +46,7 @@ export function CancelForm({ orderDetail }: CancelFormProps) {
4646
const [submitting, setSubmitting] = useState(false);
4747
const [addToCart, setAddToCart] = useState(false);
4848
const [showModal, setShowModal] = useState(false);
49+
const [alertMessage, setAlertMessage] = useState<string | null>(null);
4950
const [cancelResult, setCancelResult] = useState<OrderCancelResponse | null>(
5051
null,
5152
);
@@ -64,7 +65,11 @@ export function CancelForm({ orderDetail }: CancelFormProps) {
6465
})
6566
.catch((err) => {
6667
console.error(err);
67-
alert('환불 정보를 불러오지 못했습니다.');
68+
setAlertMessage(
69+
err instanceof Error
70+
? err.message
71+
: '환불 정보를 불러오지 못했습니다.',
72+
);
6873
setStep('reason');
6974
})
7075
.finally(() => setRefundLoading(false));
@@ -87,14 +92,32 @@ export function CancelForm({ orderDetail }: CancelFormProps) {
8792
setShowModal(false);
8893
setStep('complete');
8994
} catch (error) {
90-
alert(
95+
setShowModal(false);
96+
setAlertMessage(
9197
error instanceof Error ? error.message : '주문 취소에 실패했습니다.',
9298
);
9399
} finally {
94100
setSubmitting(false);
95101
}
96102
};
97103

104+
// --- 알림 모달 ---
105+
if (alertMessage) {
106+
return (
107+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
108+
<div className="mx-5 w-full max-w-md rounded-2xl bg-white p-6">
109+
<p className="mb-6 text-center text-xl font-bold">{alertMessage}</p>
110+
<button
111+
className="bg-ongil-teal w-full rounded-xl py-3 text-lg text-white"
112+
onClick={() => router.replace('/orders')}
113+
>
114+
주문 내역으로 돌아가기
115+
</button>
116+
</div>
117+
</div>
118+
);
119+
}
120+
98121
// --- 완료 단계 ---
99122
if (step === 'complete' && cancelResult) {
100123
const orderSummary: OrderSummary = {

src/app/orders/[orderId]/cancel/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { getOrderDetail } from '@/app/actions/order';
33
import { notFound } from 'next/navigation';
44
import { CloseXButton } from '@/components/ui/close-button';
55
import { CancelForm } from './_components/cancel-form';
6+
import { auth } from '/auth';
7+
import { redirect } from 'next/navigation';
68

79
export const metadata: Metadata = {
810
title: '주문 취소 | OnGil',
@@ -14,6 +16,8 @@ interface CancelPageProps {
1416
}
1517

1618
export default async function CancelReasonPage({ params }: CancelPageProps) {
19+
const session = await auth();
20+
if (!session) redirect('/login');
1721
const { orderId } = await params;
1822
const numericId = Number(orderId);
1923
if (Number.isNaN(numericId)) {

src/app/orders/[orderId]/page.tsx

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Image from 'next/image';
33
import Link from 'next/link';
44
import { getOrderDetail } from '@/app/actions/order';
55
import { CloseXButton } from '@/components/ui/close-button';
6-
import { DeleteOrderButton } from '@/components/orders/delete-order-button';
6+
import DeleteOrderButton from '@/components/orders/delete-order-button';
77
import { notFound } from 'next/navigation';
88

99
export const metadata: Metadata = {
@@ -37,6 +37,11 @@ export default async function OrderDetailPage({ params }: OrderPageProps) {
3737
const formatPrice = (price: number) => {
3838
return price.toLocaleString('ko-KR');
3939
};
40+
const itemsTotal = order.orderItems.reduce(
41+
(sum, item) => sum + item.priceAtOrder * item.quantity,
42+
0,
43+
);
44+
const discountAmount = itemsTotal - order.totalAmount;
4045

4146
return (
4247
<main className="mx-auto min-h-screen max-w-2xl bg-white px-5 pb-20 leading-normal">
@@ -119,31 +124,13 @@ export default async function OrderDetailPage({ params }: OrderPageProps) {
119124
<div className="rounded-xl border-2 border-gray-300 p-5 text-lg">
120125
<div className="flex justify-between py-2">
121126
<span>상품 금액</span>
122-
<span>
123-
{formatPrice(
124-
order.orderItems.reduce(
125-
(sum, item) => sum + item.priceAtOrder * item.quantity,
126-
0,
127-
),
128-
)}
129-
130-
</span>
127+
<span>{formatPrice(itemsTotal)}</span>
131128
</div>
132-
{order.orderItems.reduce(
133-
(sum, item) => sum + item.priceAtOrder * item.quantity,
134-
0,
135-
) - order.totalAmount > 0 && (
129+
{discountAmount > 0 && (
136130
<div className="flex justify-between py-2">
137131
<span>할인 금액</span>
138132
<span className="text-red-500">
139-
-
140-
{formatPrice(
141-
order.orderItems.reduce(
142-
(sum, item) => sum + item.priceAtOrder * item.quantity,
143-
0,
144-
) - order.totalAmount,
145-
)}
146-
133+
-{formatPrice(discountAmount)}
147134
</span>
148135
</div>
149136
)}

src/app/orders/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Metadata } from 'next';
22
import Image from 'next/image';
33
import Link from 'next/link';
4+
import { redirect } from 'next/navigation';
5+
import { auth } from '/auth';
46
import { getOrders } from '@/app/actions/order';
57
import { getDefaultDateRange } from '@/lib/date-utils';
68
import { OrderList } from '@/components/orders/order-list';
@@ -13,6 +15,9 @@ export const metadata: Metadata = {
1315
};
1416

1517
export default async function OrderListPage() {
18+
const session = await auth();
19+
if (!session) redirect('/login');
20+
1621
const defaults = getDefaultDateRange('1m');
1722
const response = await getOrders({
1823
startDate: defaults.startDate,

src/components/orders/delete-order-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface DeleteOrderButtonProps {
88
orderId: number;
99
}
1010

11-
export function DeleteOrderButton({ orderId }: DeleteOrderButtonProps) {
11+
export default function DeleteOrderButton({ orderId }: DeleteOrderButtonProps) {
1212
const router = useRouter();
1313
const [showModal, setShowModal] = useState(false);
1414
const [deleting, setDeleting] = useState(false);

src/components/orders/order-list-card.tsx

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
11
'use client';
22

3+
import { useState } from 'react';
34
import { useRouter } from 'next/navigation';
45
import Image from 'next/image';
56
import { Card, CardContent } from '@/components/ui/card';
67
import { Button } from '@/components/ui/button';
78
import { OrderSummary } from '@/types/domain/order';
89

10+
const STATUS_LABEL: Record<string, string> = {
11+
ORDER_RECEIVED: '주문 완료',
12+
CANCELLED: '주문 취소',
13+
};
14+
915
interface OrderListCardProps {
1016
order: OrderSummary;
1117
}
1218

13-
export function OrderListCard({ order }: OrderListCardProps) {
19+
export default function OrderListCard({ order }: OrderListCardProps) {
1420
const router = useRouter();
1521
const repItem = order.items[0];
22+
const [showAlert, setShowAlert] = useState(false);
23+
const isCancelled = String(order.orderStatus).includes('CANCEL');
24+
25+
const handleCancelClick = () => {
26+
if (isCancelled) {
27+
setShowAlert(true);
28+
} else {
29+
router.push(`/orders/${order.orderId}/cancel`);
30+
}
31+
};
1632

1733
return (
1834
<Card className="rounded-lg border-black p-5">
@@ -25,7 +41,7 @@ export function OrderListCard({ order }: OrderListCardProps) {
2541
</span>
2642
{/* 상태(주문 완료/취소 인지) */}
2743
<span className="text-xl leading-normal font-bold text-[#FF0000]">
28-
{order.orderStatus}
44+
{STATUS_LABEL[order.orderStatus] ?? order.orderStatus}
2945
</span>
3046
</div>
3147
</div>
@@ -62,7 +78,7 @@ export function OrderListCard({ order }: OrderListCardProps) {
6278
<Button
6379
variant="outline"
6480
className="h-full rounded-md bg-[#C1C1C1] text-xl"
65-
onClick={() => router.push(`/orders/${order.orderId}/cancel`)}
81+
onClick={handleCancelClick}
6682
>
6783
<span>상품 취소하기</span>
6884
</Button>
@@ -74,6 +90,22 @@ export function OrderListCard({ order }: OrderListCardProps) {
7490
</Button>
7591
</div>
7692
</CardContent>
93+
94+
{showAlert && (
95+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
96+
<div className="mx-5 w-full max-w-md rounded-2xl bg-white p-6">
97+
<p className="mb-6 text-center text-xl font-bold">
98+
이미 취소된 주문입니다.
99+
</p>
100+
<button
101+
className="bg-ongil-teal w-full rounded-xl py-3 text-lg text-white"
102+
onClick={() => setShowAlert(false)}
103+
>
104+
확인
105+
</button>
106+
</div>
107+
</div>
108+
)}
77109
</Card>
78110
);
79111
}

src/components/orders/order-list.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useState } from 'react';
44
import { Button } from '@/components/ui/button';
5-
import { OrderListCard } from '@/components/orders/order-list-card';
5+
import OrderListCard from '@/components/orders/order-list-card';
66
import {
77
OrderSearchModal,
88
type OrderSearchParams,
@@ -99,7 +99,7 @@ export function OrderList({
9999
{keyword || '검색어를 입력하세요'}
100100
</span>
101101
<Image
102-
src="icons/search.svg"
102+
src="/icons/search.svg"
103103
alt="검색 아이콘"
104104
width={26}
105105
height={26}

src/lib/date-utils.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
11
export type PeriodPreset = 'custom' | '1m' | '6m' | '1y';
22

3+
function formatLocalDate(date: Date): string {
4+
const y = date.getFullYear();
5+
const m = String(date.getMonth() + 1).padStart(2, '0');
6+
const d = String(date.getDate()).padStart(2, '0');
7+
return `${y}-${m}-${d}`;
8+
}
9+
10+
function subtractMonths(date: Date, months: number): Date {
11+
const result = new Date(date);
12+
const targetMonth = result.getMonth() - months;
13+
result.setMonth(targetMonth);
14+
if (result.getMonth() !== ((targetMonth % 12) + 12) % 12) {
15+
result.setDate(0);
16+
}
17+
return result;
18+
}
19+
320
export function getDefaultDateRange(preset: Exclude<PeriodPreset, 'custom'>) {
421
const today = new Date();
5-
const end = today.toISOString().split('T')[0];
6-
const start = new Date();
22+
const endDate = formatLocalDate(today);
723

8-
if (preset === '1m') start.setMonth(today.getMonth() - 1);
9-
else if (preset === '6m') start.setMonth(today.getMonth() - 6);
10-
else if (preset === '1y') start.setFullYear(today.getFullYear() - 1);
24+
let start: Date;
25+
if (preset === '1m') start = subtractMonths(today, 1);
26+
else if (preset === '6m') start = subtractMonths(today, 6);
27+
else
28+
start = new Date(
29+
today.getFullYear() - 1,
30+
today.getMonth(),
31+
today.getDate(),
32+
);
1133

12-
return { startDate: start.toISOString().split('T')[0], endDate: end };
34+
return { startDate: formatLocalDate(start), endDate };
1335
}

0 commit comments

Comments
 (0)