/events 관련 코드 및 파일 정리

This commit is contained in:
“offinon” 2026-03-11 05:14:32 +00:00
parent ec9511ecd2
commit be2b3ef1ca
20 changed files with 29 additions and 377 deletions

View File

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 315 KiB

After

Width:  |  Height:  |  Size: 315 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 658 KiB

After

Width:  |  Height:  |  Size: 658 KiB

View File

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

View File

Before

Width:  |  Height:  |  Size: 467 KiB

After

Width:  |  Height:  |  Size: 467 KiB

View File

@ -80,11 +80,11 @@ export default async function CancellationPage() {
<span className="">{order.customer.name}</span>
</div>
</TableCell>
<TableCell className="text-zinc-500">{order.event.productType}</TableCell>
<TableCell className="text-zinc-500">{order.product.productType}</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Avatar src={order.event.thumbUrl} className="size-6" />
<span className="max-w-[150px] truncate">{order.event.name}</span>
<Avatar src={order.product.thumbUrl} className="size-6" />
<span className="max-w-[150px] truncate">{order.product.name}</span>
</div>
</TableCell>
<TableCell className="text-right font-semibold ">{order.amount.krw}</TableCell>

View File

@ -1,90 +0,0 @@
import { Stat } from '@/app/stat'
import { Badge } from '@/components/badge'
import { Button } from '@/components/button'
import { Heading, Subheading } from '@/components/heading'
import { Link } from '@/components/link'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/table'
import { getEvent, getEventOrders } from '@/data'
import { ChevronLeftIcon } from '@heroicons/react/16/solid'
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
let { id } = await params
let event = await getEvent(id)
return {
title: event?.name,
}
}
export default async function Event({ params }: { params: Promise<{ id: string }> }) {
let { id } = await params
let event = await getEvent(id)
let orders = await getEventOrders(id)
if (!event) {
notFound()
}
return (
<>
<div className="max-lg:hidden">
<Link href="/events" className="inline-flex items-center gap-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
<ChevronLeftIcon className="size-4 fill-zinc-400 dark:fill-zinc-500" />
Events
</Link>
</div>
<div className="mt-4 flex flex-wrap items-end justify-between gap-4">
<div className="flex flex-wrap items-center gap-6">
<div className="w-32 shrink-0">
<img className="aspect-3/2 rounded-lg shadow-sm" src={event.imgUrl} alt="" />
</div>
<div>
<div className="flex flex-wrap items-center gap-x-4 gap-y-2">
<Heading>{event.name}</Heading>
<Badge color={event.status === 'On Sale' ? 'lime' : 'zinc'}>{event.status}</Badge>
</div>
<div className="mt-2 text-sm/6 text-zinc-500">
{event.date} at {event.time} <span aria-hidden="true">·</span> {event.location}
</div>
</div>
</div>
<div className="flex gap-4">
<Button outline>Edit</Button>
<Button>View</Button>
</div>
</div>
<div className="mt-8 grid gap-8 sm:grid-cols-3">
<Stat title="Total revenue" value={event.totalRevenue} change={event.totalRevenueChange} />
<Stat
title="Tickets sold"
value={`${event.ticketsSold}/${event.ticketsAvailable}`}
change={event.ticketsSoldChange}
/>
<Stat title="Pageviews" value={event.pageViews} change={event.pageViewsChange} />
</div>
<Subheading className="mt-12">Recent orders</Subheading>
<Table className="mt-4 [--gutter:--spacing(6)] lg:[--gutter:--spacing(10)]">
<TableHead>
<TableRow>
<TableHeader>Order number</TableHeader>
<TableHeader>Purchase date</TableHeader>
<TableHeader>Customer</TableHeader>
<TableHeader className="text-right">Amount</TableHeader>
</TableRow>
</TableHead>
<TableBody>
{orders.map((order) => (
<TableRow key={order.id} href={order.url} title={`Order #${order.id}`}>
<TableCell>{order.id}</TableCell>
<TableCell className="text-zinc-500">{order.date}</TableCell>
<TableCell>{order.customer.name}</TableCell>
<TableCell className="text-right">US{order.amount.usd}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</>
)
}

View File

@ -1,87 +0,0 @@
import { Badge } from '@/components/badge'
import { Button } from '@/components/button'
import { Divider } from '@/components/divider'
import { Dropdown, DropdownButton, DropdownItem, DropdownMenu } from '@/components/dropdown'
import { Heading } from '@/components/heading'
import { Input, InputGroup } from '@/components/input'
import { Link } from '@/components/link'
import { Select } from '@/components/select'
import { getEvents } from '@/data'
import { EllipsisVerticalIcon, MagnifyingGlassIcon } from '@heroicons/react/16/solid'
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Events',
}
export default async function Events() {
let events = await getEvents()
return (
<>
<div className="flex flex-wrap items-end justify-between gap-4">
<div className="max-sm:w-full sm:flex-1">
<Heading>Events</Heading>
<div className="mt-4 flex max-w-xl gap-4">
<div className="flex-1">
<InputGroup>
<MagnifyingGlassIcon />
<Input name="search" placeholder="Search events&hellip;" />
</InputGroup>
</div>
<div>
<Select name="sort_by">
<option value="name">Sort by name</option>
<option value="date">Sort by date</option>
<option value="status">Sort by status</option>
</Select>
</div>
</div>
</div>
<Button>Create event</Button>
</div>
<ul className="mt-10">
{events.map((event, index) => (
<li key={event.id}>
<Divider soft={index > 0} />
<div className="flex items-center justify-between">
<div key={event.id} className="flex gap-6 py-6">
<div className="w-32 shrink-0">
<Link href={event.url} aria-hidden="true">
<img className="aspect-3/2 rounded-lg shadow-sm" src={event.imgUrl} alt="" />
</Link>
</div>
<div className="space-y-1.5">
<div className="text-base/6 font-semibold">
<Link href={event.url}>{event.name}</Link>
</div>
<div className="text-xs/6 text-zinc-500">
{event.date} at {event.time} <span aria-hidden="true">·</span> {event.location}
</div>
<div className="text-xs/6 text-zinc-600">
{event.ticketsSold}/{event.ticketsAvailable} tickets sold
</div>
</div>
</div>
<div className="flex items-center gap-4">
<Badge className="max-sm:hidden" color={event.status === 'On Sale' ? 'lime' : 'zinc'}>
{event.status}
</Badge>
<Dropdown>
<DropdownButton plain aria-label="More options">
<EllipsisVerticalIcon />
</DropdownButton>
<DropdownMenu anchor="bottom end">
<DropdownItem href={event.url}>View</DropdownItem>
<DropdownItem>Edit</DropdownItem>
<DropdownItem>Delete</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
</div>
</li>
))}
</ul>
</>
)
}

View File

@ -75,9 +75,9 @@ export default async function Order({ params }: { params: Promise<{ id: string }
<DescriptionDetails>{order.customer.name}</DescriptionDetails>
<DescriptionTerm>Product</DescriptionTerm>
<DescriptionDetails>
<Link href={order.event.url} className="flex items-center gap-2">
<Avatar src={order.event.thumbUrl} className="size-6" />
<span>{order.event.name}</span>
<Link href={order.product.url} className="flex items-center gap-2">
<Avatar src={order.product.thumbUrl} className="size-6" />
<span>{order.product.name}</span>
</Link>
</DescriptionDetails>
<DescriptionTerm>Amount</DescriptionTerm>

View File

@ -78,15 +78,15 @@ export default async function Orders() {
<TableCell className="text-zinc-500">{order.date}</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Avatar src={order.event.thumbUser} className="size-6" />
<Avatar src={order.product.thumbUser} className="size-6" />
<span>{order.customer.name}</span>
</div>
</TableCell>
<TableCell className="text-zinc-500">{order.event.productType}</TableCell>
<TableCell className="text-zinc-500">{order.product.productType}</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Avatar src={order.event.thumbUrl} className="size-6" />
<span>{order.event.name}</span>
<Avatar src={order.product.thumbUrl} className="size-6" />
<span>{order.product.name}</span>
</div>
</TableCell>
<TableCell className="text-right">{order.amount.krw}</TableCell>

View File

@ -3,10 +3,10 @@ import type { Metadata } from 'next'
import ProductsClient from './ProductsClient'
export const metadata: Metadata = {
title: 'Events',
title: 'Products',
}
export default async function EventsPage() {
export default async function ProductsPage() {
const products = await getProducts()
return <ProductsClient products={products} />

View File

@ -75,11 +75,11 @@ export default async function Order({ params }: { params: Promise<{ id: string }
<DescriptionList>
<DescriptionTerm>Customer</DescriptionTerm>
<DescriptionDetails>{order.customer.name}</DescriptionDetails>
<DescriptionTerm>Event</DescriptionTerm>
<DescriptionTerm>Product</DescriptionTerm>
<DescriptionDetails>
<Link href={order.event.url} className="flex items-center gap-2">
<Avatar src={order.event.thumbUrl} className="size-6" />
<span>{order.event.name}</span>
<Link href={order.product.url} className="flex items-center gap-2">
<Avatar src={order.product.thumbUrl} className="size-6" />
<span>{order.product.name}</span>
</Link>
</DescriptionDetails>
<DescriptionTerm>Amount</DescriptionTerm>

View File

@ -24,7 +24,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
// 취소 데이터 추가
isCancelled: true,
@ -49,7 +48,6 @@ export async function getOrders() {
country: 'USA',
countryFlagUrl: '/flags/us.svg',
},
event: await getEvent('1001'),
product: await getProduct('1001'),
isCancelled: true,
cancellationDate: '2024년 5월 6일 09:15',
@ -74,7 +72,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1002'),
product: await getProduct('1002'),
isCancelled: true,
cancellationDate: '2024년 4월 29일 18:40',
@ -99,7 +96,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: false,
},
@ -119,7 +115,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -139,7 +134,6 @@ export async function getOrders() {
country: 'USA',
countryFlagUrl: '/flags/us.svg',
},
event: await getEvent('1001'),
product: await getProduct('1001'),
isCancelled: true,
cancellationDate: '2024년 4월 15일 11:30',
@ -163,7 +157,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1002'),
product: await getProduct('1002'),
isCancelled: false,
},
@ -183,7 +176,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: true,
cancellationDate: '2024년 4월 7일 10:05',
@ -208,7 +200,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: false,
},
@ -228,7 +219,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -248,7 +238,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1001'),
product: await getProduct('1001'),
isCancelled: false,
},
@ -268,7 +257,6 @@ export async function getOrders() {
country: 'USA',
countryFlagUrl: '/flags/us.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: false,
},
@ -288,7 +276,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1002'),
product: await getProduct('1002'),
isCancelled: false,
},
@ -308,7 +295,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1001'),
product: await getProduct('1001'),
isCancelled: false,
},
@ -328,7 +314,6 @@ export async function getOrders() {
country: 'USA',
countryFlagUrl: '/flags/us.svg',
},
event: await getEvent('1002'),
product: await getProduct('1002'),
isCancelled: false,
},
@ -348,7 +333,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1002'),
product: await getProduct('1002'),
isCancelled: false,
},
@ -368,7 +352,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: false,
},
@ -388,7 +371,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: false,
},
@ -408,7 +390,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -428,7 +409,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -448,7 +428,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1001'),
product: await getProduct('1001'),
isCancelled: false,
},
@ -468,7 +447,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1000'),
product: await getProduct('1000'),
isCancelled: false,
},
@ -488,7 +466,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -508,7 +485,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -528,7 +504,6 @@ export async function getOrders() {
country: 'Canada',
countryFlagUrl: '/flags/ca.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
@ -548,164 +523,18 @@ export async function getOrders() {
country: 'USA',
countryFlagUrl: '/flags/us.svg',
},
event: await getEvent('1003'),
product: await getProduct('1003'),
isCancelled: false,
},
]
}
export async function getEvent(id: string) {
return (await getEvents()).find((event) => event.id.toString() === id)!
}
export async function getProduct(id: string) {
return (await getProducts()).find((product) => product.id.toString() === id)!
}
export async function getEventOrders(id: string) {
return (await getOrders()).filter((order) => order.event.id.toString() === id)
}
export async function getProductOrders(id: string) {
return (await getOrders()).filter((order) => order.event.id.toString() === id)
}
export async function getEvents() {
return [
{
id: 1000,
name: 'Bear Hug: Live in Concert',
url: '/events/1000',
date: '2024년 5월 20일',
time: '오후 10시',
location: 'Harmony Theater, Winnipeg, MB',
totalRevenue: '102,552',
totalRevenueChange: '+3.2%',
ticketsAvailable: 500,
ticketsSold: 350,
ticketsSoldChange: '+8.1%',
pageViews: '24,300',
pageViewsChange: '-0.75%',
status: '판매 중',
productType: '애셋',
licenseType: '전체 변경',
itemPrice: '45,000원',
imgUrl: '/events/bear-hug.jpg',
thumbUrl: '/events/bear-hug-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
id: 1001,
name: 'Six Fingers — DJ Set',
url: '/events/1001',
date: '2024년 6월 2일',
time: '오후 8시',
location: 'Moonbeam Arena, Uxbridge, ON',
totalRevenue: '24,115',
totalRevenueChange: '+3.2%',
ticketsAvailable: 150,
ticketsSold: 72,
ticketsSoldChange: '+8.1%',
pageViews: '57,544',
pageViewsChange: '-2.5%',
status: '판매 중',
productType: '텍스처',
licenseType: '일반',
itemPrice: '12,000원',
imgUrl: '/events/six-fingers.jpg',
thumbUrl: '/events/six-fingers-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
id: 1002,
name: 'We All Look The Same',
url: '/events/1002',
date: '2024년 8월 5일',
time: '오후 4시',
location: 'Electric Coliseum, New York, NY',
totalRevenue: '40,598',
totalRevenueChange: '+3.2%',
ticketsAvailable: 275,
ticketsSold: 275,
ticketsSoldChange: '+8.1%',
pageViews: '122,122',
pageViewsChange: '-8.0%',
status: '미판매',
productType: '애셋',
licenseType: '단순 읽기',
itemPrice: 'Free',
imgUrl: '/events/we-all-look-the-same.jpg',
thumbUrl: '/events/we-all-look-the-same-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
id: 1003,
name: 'Viking People',
url: '/events/1003',
date: '2024년 12월 31일',
time: '오후 8시',
location: 'Tapestry Hall, Cambridge, ON',
totalRevenue: '3,552',
totalRevenueChange: '+3.2%',
ticketsAvailable: 40,
ticketsSold: 6,
ticketsSoldChange: '+8.1%',
pageViews: '9,000',
pageViewsChange: '-0.15%',
status: '판매 중',
productType: '텍스처',
licenseType: '일반',
itemPrice: '25,500원',
imgUrl: '/events/viking-people.jpg',
thumbUrl: '/events/viking-people-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
id: 1004,
name: 'FE1220_Assets conf set',
url: '/events/1004',
date: '2024년 5월 20일',
time: '오후 10시',
location: 'Harmony Theater, Winnipeg, MB',
totalRevenue: '102,552',
totalRevenueChange: '+3.2%',
ticketsAvailable: 500,
ticketsSold: 350,
ticketsSoldChange: '+8.1%',
pageViews: '24,300',
pageViewsChange: '-0.75%',
status: '판매 중지',
productType: '애셋',
licenseType: '전체 변경',
itemPrice: '45,000원',
imgUrl: '/events/bear-hug.jpg',
thumbUrl: '/events/bear-hug-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
id: 1005,
name: 'Six Fingers — DJ Set',
url: '/events/1005',
date: '2024년 6월 2일',
time: '오후 8시',
location: 'Moonbeam Arena, Uxbridge, ON',
totalRevenue: '24,115',
totalRevenueChange: '+3.2%',
ticketsAvailable: 150,
ticketsSold: 72,
ticketsSoldChange: '+8.1%',
pageViews: '57,544',
pageViewsChange: '-2.5%',
status: '판매 보류',
productType: '텍스처',
licenseType: '일반',
itemPrice: '12,000원',
imgUrl: '/events/six-fingers.jpg',
thumbUrl: '/events/six-fingers-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
]
return (await getOrders()).filter((order) => order.product.id.toString() === id)
}
export function getCountries() {
@ -944,8 +773,8 @@ export async function getProducts() {
productType: '애셋',
licenseType: '전체 변경',
itemPrice: '45,000원',
imgUrl: '/events/bear-hug.jpg',
thumbUrl: '/events/bear-hug-thumb.jpg',
imgUrl: '/products/bear-hug.jpg',
thumbUrl: '/products/bear-hug-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
@ -966,8 +795,8 @@ export async function getProducts() {
productType: '텍스처',
licenseType: '일반',
itemPrice: '12,000원',
imgUrl: '/events/six-fingers.jpg',
thumbUrl: '/events/six-fingers-thumb.jpg',
imgUrl: '/products/six-fingers.jpg',
thumbUrl: '/products/six-fingers-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
@ -988,8 +817,8 @@ export async function getProducts() {
productType: '애셋',
licenseType: '단순 읽기',
itemPrice: 'Free',
imgUrl: '/events/we-all-look-the-same.jpg',
thumbUrl: '/events/we-all-look-the-same-thumb.jpg',
imgUrl: '/products/we-all-look-the-same.jpg',
thumbUrl: '/products/we-all-look-the-same-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
@ -1010,8 +839,8 @@ export async function getProducts() {
productType: '텍스처',
licenseType: '일반',
itemPrice: '25,500원',
imgUrl: '/events/viking-people.jpg',
thumbUrl: '/events/viking-people-thumb.jpg',
imgUrl: '/products/viking-people.jpg',
thumbUrl: '/products/viking-people-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
@ -1032,8 +861,8 @@ export async function getProducts() {
productType: '애셋',
licenseType: '전체 변경',
itemPrice: '45,000원',
imgUrl: '/events/bear-hug.jpg',
thumbUrl: '/events/bear-hug-thumb.jpg',
imgUrl: '/products/bear-hug.jpg',
thumbUrl: '/products/bear-hug-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
{
@ -1054,8 +883,8 @@ export async function getProducts() {
productType: '텍스처',
licenseType: '일반',
itemPrice: '12,000원',
imgUrl: '/events/six-fingers.jpg',
thumbUrl: '/events/six-fingers-thumb.jpg',
imgUrl: '/products/six-fingers.jpg',
thumbUrl: '/products/six-fingers-thumb.jpg',
thumbUser: '/users/erica.jpg',
},
]