diff --git a/apps/owner/src/app/(tabs)/order/_components/OrderHistoryCard.tsx b/apps/owner/src/app/(tabs)/order/_components/OrderHistoryCard.tsx
new file mode 100644
index 0000000..50161f8
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_components/OrderHistoryCard.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import { Card } from "@compasser/design-system";
+import type { ReservationItem } from "../_types/order";
+import { getStatusClassName, getStatusLabel } from "../_utils/orderStatus";
+
+interface OrderHistoryCardProps {
+ order: ReservationItem;
+}
+
+export default function OrderHistoryCard({ order }: OrderHistoryCardProps) {
+ return (
+
+
+
+ 주문자
+ {order.customerName}
+
+ {getStatusLabel(order.status)}
+
+
+ 주문내역
+ {order.orderDetail}
+
+ 가격
+ {order.price}
+
+ 수량
+ {order.quantity}
+
+
+
+ {order.processedAt}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_components/OrderList.tsx b/apps/owner/src/app/(tabs)/order/_components/OrderList.tsx
new file mode 100644
index 0000000..3426408
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_components/OrderList.tsx
@@ -0,0 +1,44 @@
+"use client";
+
+import ReservationCard from "./ReservationCard";
+import OrderHistoryCard from "./OrderHistoryCard";
+import type { OrderTabKey, ReservationItem } from "../_types/order";
+
+interface OrderListProps {
+ activeTab: OrderTabKey;
+ orders: ReservationItem[];
+ onAccept: (orderId: number) => void;
+ onReject: (orderId: number) => void;
+}
+
+export default function OrderList({
+ activeTab,
+ orders,
+ onAccept,
+ onReject,
+}: OrderListProps) {
+ if (orders.length === 0) {
+ return (
+
+ );
+ }
+
+ return (
+
+ {activeTab === "reservation"
+ ? orders.map((order) => (
+
+ ))
+ : orders.map((order) => (
+
+ ))}
+
+ );
+}
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_components/ReservationCard.tsx b/apps/owner/src/app/(tabs)/order/_components/ReservationCard.tsx
new file mode 100644
index 0000000..3798d41
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_components/ReservationCard.tsx
@@ -0,0 +1,70 @@
+"use client";
+
+import { Card, Button } from "@compasser/design-system";
+import type { ReservationItem } from "../_types/order";
+import { getStatusClassName, getStatusLabel } from "../_utils/orderStatus";
+
+interface ReservationCardProps {
+ order: ReservationItem;
+ onAccept: (orderId: number) => void;
+ onReject: (orderId: number) => void;
+}
+
+export default function ReservationCard({
+ order,
+ onAccept,
+ onReject,
+}: ReservationCardProps) {
+ const isPending = order.status === "pending";
+
+ return (
+
+
+
+ 주문자
+ {order.customerName}
+
+ {getStatusLabel(order.status)}
+
+
+ 주문내역
+ {order.orderDetail}
+
+ 가격
+ {order.price}
+
+ 수량
+ {order.quantity}
+
+
+ {isPending ? (
+
+
+
+
+
+ ) : (
+
+ {order.processedAt}
+
+ )}
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_components/modal/AcceptOrderModal.tsx b/apps/owner/src/app/(tabs)/order/_components/modal/AcceptOrderModal.tsx
new file mode 100644
index 0000000..9f02132
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_components/modal/AcceptOrderModal.tsx
@@ -0,0 +1,49 @@
+"use client";
+
+import { Button, Modal } from "@compasser/design-system";
+
+interface AcceptOrderModalProps {
+ open: boolean;
+ onClose: () => void;
+ onConfirm: () => void;
+}
+
+export default function AcceptOrderModal({
+ open,
+ onClose,
+ onConfirm,
+}: AcceptOrderModalProps) {
+ return (
+
+
+
+
+
+ }
+ />
+ );
+}
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_components/modal/RejectOrderModal.tsx b/apps/owner/src/app/(tabs)/order/_components/modal/RejectOrderModal.tsx
new file mode 100644
index 0000000..75a3f49
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_components/modal/RejectOrderModal.tsx
@@ -0,0 +1,73 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import { Button, Modal } from "@compasser/design-system";
+
+interface RejectOrderModalProps {
+ open: boolean;
+ onClose: () => void;
+ onConfirm: (reason: string) => void;
+}
+
+export default function RejectOrderModal({
+ open,
+ onClose,
+ onConfirm,
+}: RejectOrderModalProps) {
+ const [reason, setReason] = useState("");
+
+ useEffect(() => {
+ if (!open) {
+ setReason("");
+ }
+ }, [open]);
+
+ return (
+
+
+
+
+
+ }
+ >
+
+ setReason(e.target.value)}
+ placeholder="거절 사유를 입력해주세요."
+ className="
+ w-full rounded-[8px] border border-primary
+ px-[1rem] py-[0.6rem]
+ body2-r text-default
+ placeholder:body2-r placeholder:text-gray-300
+ outline-none
+ "
+ />
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_constants/mockOrders.ts b/apps/owner/src/app/(tabs)/order/_constants/mockOrders.ts
new file mode 100644
index 0000000..3a72761
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_constants/mockOrders.ts
@@ -0,0 +1,36 @@
+import type { ReservationItem } from "../_types/order";
+
+export const INITIAL_RESERVATIONS: ReservationItem[] = [
+ {
+ id: 1,
+ customerName: "김00",
+ orderDetail: "랜덤박스 1레벨",
+ price: "6,000원",
+ quantity: "1개",
+ status: "pending",
+ },
+ {
+ id: 2,
+ customerName: "고00",
+ orderDetail: "랜덤박스 1레벨",
+ price: "6,000원",
+ quantity: "1개",
+ status: "pending",
+ },
+ {
+ id: 3,
+ customerName: "이00",
+ orderDetail: "랜덤박스 3레벨",
+ price: "12,000원",
+ quantity: "2개",
+ status: "pending",
+ },
+ {
+ id: 4,
+ customerName: "박00",
+ orderDetail: "랜덤박스 2레벨",
+ price: "9,000원",
+ quantity: "3개",
+ status: "pending",
+ }
+];
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_types/order.ts b/apps/owner/src/app/(tabs)/order/_types/order.ts
new file mode 100644
index 0000000..2d48126
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_types/order.ts
@@ -0,0 +1,23 @@
+export type OrderTabKey = "reservation" | "order";
+
+export type ReservationStatus = "pending" | "completed" | "cancelled";
+
+export interface ReservationItem {
+ id: number;
+ customerName: string;
+ orderDetail: string;
+ price: string;
+ quantity: string;
+ status: ReservationStatus;
+ processedAt?: string;
+}
+
+export interface AcceptModalState {
+ isOpen: boolean;
+ orderId: number | null;
+}
+
+export interface RejectModalState {
+ isOpen: boolean;
+ orderId: number | null;
+}
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_utils/formatProcessAt.ts b/apps/owner/src/app/(tabs)/order/_utils/formatProcessAt.ts
new file mode 100644
index 0000000..b74de73
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_utils/formatProcessAt.ts
@@ -0,0 +1,7 @@
+export const formatProcessedAt = (date: Date) => {
+ const year = String(date.getFullYear()).slice(2);
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+
+ return `${year}/${month}/${day}`;
+};
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/_utils/orderStatus.ts b/apps/owner/src/app/(tabs)/order/_utils/orderStatus.ts
new file mode 100644
index 0000000..d5bf8a4
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/_utils/orderStatus.ts
@@ -0,0 +1,27 @@
+import type { ReservationStatus } from "../_types/order";
+
+export const getStatusLabel = (status: ReservationStatus) => {
+ switch (status) {
+ case "pending":
+ return "확인 대기중";
+ case "completed":
+ return "거래완료";
+ case "cancelled":
+ return "거래취소";
+ default:
+ return "";
+ }
+};
+
+export const getStatusClassName = (status: ReservationStatus) => {
+ switch (status) {
+ case "pending":
+ return "body1-m text-secondary";
+ case "completed":
+ return "body1-m text-primary";
+ case "cancelled":
+ return "body1-m text-gray-500";
+ default:
+ return "";
+ }
+};
\ No newline at end of file
diff --git a/apps/owner/src/app/(tabs)/order/page.tsx b/apps/owner/src/app/(tabs)/order/page.tsx
new file mode 100644
index 0000000..0bd8071
--- /dev/null
+++ b/apps/owner/src/app/(tabs)/order/page.tsx
@@ -0,0 +1,153 @@
+"use client";
+
+import { useMemo, useState } from "react";
+import { Header, TopTabBar } from "@compasser/design-system";
+import OrderList from "./_components/OrderList";
+import AcceptOrderModal from "./_components/modal/AcceptOrderModal";
+import RejectOrderModal from "./_components/modal/RejectOrderModal";
+import { INITIAL_RESERVATIONS } from "./_constants/mockOrders";
+import { formatProcessedAt } from "./_utils/formatProcessAt";
+import type {
+ AcceptModalState,
+ OrderTabKey,
+ RejectModalState,
+ ReservationItem,
+} from "./_types/order";
+
+export default function OrderStatusPage() {
+ const [activeTab, setActiveTab] = useState("reservation");
+ const [orders, setOrders] = useState(INITIAL_RESERVATIONS);
+ const isOrderTabKey = (key: string): key is OrderTabKey =>
+ key === "reservation" || key === "order";
+
+ const [acceptModal, setAcceptModal] = useState({
+ isOpen: false,
+ orderId: null,
+ });
+
+ const [rejectModal, setRejectModal] = useState({
+ isOpen: false,
+ orderId: null,
+ });
+
+ const reservationOrders = useMemo(
+ () => orders.filter((order) => order.status === "pending"),
+ [orders]
+ );
+
+ const completedOrders = useMemo(
+ () => orders.filter((order) => order.status !== "pending"),
+ [orders]
+ );
+
+ const currentOrders =
+ activeTab === "reservation" ? reservationOrders : completedOrders;
+
+ const openAcceptModal = (orderId: number) => {
+ setAcceptModal({
+ isOpen: true,
+ orderId,
+ });
+ };
+
+ const closeAcceptModal = () => {
+ setAcceptModal({
+ isOpen: false,
+ orderId: null,
+ });
+ };
+
+ const openRejectModal = (orderId: number) => {
+ setRejectModal({
+ isOpen: true,
+ orderId,
+ });
+ };
+
+ const closeRejectModal = () => {
+ setRejectModal({
+ isOpen: false,
+ orderId: null,
+ });
+ };
+
+ const handleAcceptOrder = () => {
+ if (acceptModal.orderId === null) return;
+
+ const now = formatProcessedAt(new Date());
+
+ setOrders((prev) =>
+ prev.map((order) =>
+ order.id === acceptModal.orderId
+ ? {
+ ...order,
+ status: "completed",
+ processedAt: now,
+ }
+ : order
+ )
+ );
+
+ closeAcceptModal();
+ };
+
+ const handleRejectOrder = (_reason: string) => {
+ if (rejectModal.orderId === null) return;
+
+ const now = formatProcessedAt(new Date());
+
+ setOrders((prev) =>
+ prev.map((order) =>
+ order.id === rejectModal.orderId
+ ? {
+ ...order,
+ status: "cancelled",
+ processedAt: now,
+ }
+ : order
+ )
+ );
+
+ closeRejectModal();
+ };
+
+ return (
+ <>
+
+
+
+ {
+ if (isOrderTabKey(key)) setActiveTab(key);
+ }}
+ />
+
+
+
+
+
+
+
+ >
+ );
+}
\ No newline at end of file