-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/#48 admin 관련 메인 페이지 및 등록 조회 상세 페이지 UI 작업 #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b3dd347
1c7acbd
c2ea5b3
b0b1db8
967898b
1388211
3ae0ffc
ee1d102
a338f35
c1456e6
2bf4d4e
bb38dda
5a09419
e232559
c8a20bc
02bceeb
94a59e2
ebcc0ee
8131e9e
4465c40
f1418c0
5038e66
b85a8ae
0a4073c
6cd082b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| 'use client' | ||
|
|
||
| import { NavermapsProvider } from 'react-naver-maps' | ||
| import { ReactNode } from 'react' | ||
|
|
||
| export const NaverMapProvider = ({ children }: { children: ReactNode }) => { | ||
| const ncpKeyId = process.env.NEXT_PUBLIC_NAVER_MAP_ID || '' | ||
|
|
||
| return <NavermapsProvider ncpKeyId={ncpKeyId}>{children}</NavermapsProvider> | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import type { IconType } from '@repo/ui/components/Icon' | ||
|
|
||
| export type Request = { | ||
| placeId: string | ||
| placeName: string | ||
| icon: IconType | ||
| requestDate: string | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { Column, Flex } from '@repo/ui/components/Layout' | ||
| import { cn } from '@repo/ui/utils/cn' | ||
| import { Text } from '@repo/ui/components/Text' | ||
| import { Icon } from '@repo/ui/components/Icon' | ||
| import { CLIENT_PATH } from '@/consts/path' | ||
| import { Request } from '@/app/_api/types' | ||
|
|
||
| export const RequestListItem = ({ | ||
| placeId, | ||
| placeName, | ||
| icon, | ||
| requestDate, | ||
| }: Request) => ( | ||
| <li> | ||
| <Column | ||
| as={'a'} | ||
| href={CLIENT_PATH.REQUEST_DETAIL(placeId)} | ||
| className={cn('gap-1', 'py-3.5', 'border-b-1 border-gray-50')} | ||
| > | ||
| <Flex className={'gap-1'}> | ||
| <Text as={'span'} variant={'title2'}> | ||
| {placeName} | ||
| </Text> | ||
| <Icon type={icon} size={18} /> | ||
| </Flex> | ||
| <Text variant={'caption2'} className={'text-gray-200'}> | ||
| 등록 신청 일자: {requestDate} | ||
| </Text> | ||
| </Column> | ||
| </li> | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { RequestListItem } from './RequestListItem' |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||
| import { Column } from '@repo/ui/components/Layout' | ||||||
| import { Text } from '@repo/ui/components/Text' | ||||||
| import { CAMPUS, type CampusType } from '@/consts/campus' | ||||||
| import { RequestListItem } from '@/app/_components/RequestListItem' | ||||||
| import { Request } from '@/app/_api/types' | ||||||
|
|
||||||
| type Props = { | ||||||
| campus: CampusType | ||||||
| requestList: Request[] | ||||||
| } | ||||||
|
|
||||||
| export const RequestsByCampus = ({ campus, requestList }: Props) => ( | ||||||
| <Column as={'section'} className={'gap-1'}> | ||||||
| <Text variant={'heading2'} className={'text-main'}> | ||||||
| {CAMPUS[campus]}캠 | ||||||
| </Text> | ||||||
| <ul> | ||||||
| {requestList.map((request) => ( | ||||||
| <RequestListItem key={request.placeName} {...request} /> | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 고유하지 않을 수 있는 key 사용
다음 diff를 적용하여 placeId를 key로 사용하세요: - <RequestListItem key={request.placeName} {...request} />
+ <RequestListItem key={request.placeId} {...request} />📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| ))} | ||||||
| </ul> | ||||||
| </Column> | ||||||
| ) | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { RequestsByCampus } from './RequestsByCampus' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,4 @@ | ||
| @import "tailwindcss"; | ||
| @import "@repo/tailwind-config"; | ||
| @import "@repo/tailwind-config"; | ||
| @plugin './hero.ts'; | ||
| @source '../../node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import { heroui } from '@heroui/theme' | ||
| import type { Config } from 'tailwindcss' | ||
|
|
||
| export default heroui() as Config |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,38 @@ | ||
| import { Column } from '@repo/ui/components/Layout' | ||
| import { Text } from '@repo/ui/components/Text' | ||
| import { Button } from '@repo/ui/components/Button' | ||
| import { VerticalScrollArea } from '@repo/ui/components/Layout' | ||
| import { RequestsByCampus } from './_components/RequestsByCampus' | ||
| import { OnlyLeftHeader } from '@repo/ui/components/Header' | ||
| import type { Request } from './_api/types' | ||
|
|
||
| const MOCK_DATA: Request[] = [ | ||
| { | ||
| placeId: '1', | ||
| placeName: '짬뽕집', | ||
| icon: 'chinese', | ||
| requestDate: '2025-10-29', | ||
| }, | ||
| { | ||
| placeId: '2', | ||
| placeName: '짬뽕집', | ||
| icon: 'chinese', | ||
| requestDate: '2025-10-29', | ||
| }, | ||
| { | ||
| placeId: '3', | ||
| placeName: '짬뽕집', | ||
| icon: 'chinese', | ||
| requestDate: '2025-10-29', | ||
| }, | ||
| ] | ||
|
|
||
| export default function Home() { | ||
| return ( | ||
| <Column> | ||
| <Text variant={'heading1'}>Hello World!</Text> | ||
| <Button size={'medium'}>버튼</Button> | ||
| </Column> | ||
| <> | ||
| <OnlyLeftHeader icon={'logo'} name={'대기중'} /> | ||
| <VerticalScrollArea className={'gap-10 p-5'}> | ||
| <RequestsByCampus campus={'SINGWAN'} requestList={MOCK_DATA} /> | ||
| <RequestsByCampus campus={'CHEANAN'} requestList={MOCK_DATA} /> | ||
| <RequestsByCampus campus={'YESAN'} requestList={MOCK_DATA} /> | ||
| </VerticalScrollArea> | ||
| </> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| 'use client' | ||
|
|
||
| import { Header } from '@repo/ui/components/Header' | ||
| import { Icon } from '@repo/ui/components/Icon' | ||
| import { Text } from '@repo/ui/components/Text' | ||
| import { Column, VerticalScrollArea } from '@repo/ui/components/Layout' | ||
| import { Banner } from '@repo/ui/components/Banner' | ||
|
|
||
| import { Location } from './_components/Location/Location' | ||
| import { Menus } from './_components/Menus/Menus' | ||
| import { Description } from './_components/Description' | ||
| import { ActionButtonGroup } from './_components/ActionButtonGroup' | ||
| import { useDisclosure } from '@heroui/react' | ||
| import { RejectModal } from '@/app/request/[id]/_components/RejectModal' | ||
| import { useRouter } from 'next/navigation' | ||
|
|
||
| export const RequestDetailPage = () => { | ||
| const { isOpen, onOpen, onOpenChange } = useDisclosure() | ||
| const { back } = useRouter() | ||
|
|
||
| return ( | ||
| <> | ||
| <Header | ||
| left={ | ||
| <button onClick={back}> | ||
| <Icon type={'arrowLeft'} /> | ||
| </button> | ||
| } | ||
| center={<Text variant={'heading2'}>우돈탄 다산본점</Text>} | ||
| /> | ||
| <VerticalScrollArea className={'flex-1 py-5'}> | ||
| <Banner contents={[]} /> | ||
| <Column className={'flex-1 justify-around gap-4 px-5'}> | ||
| <Location /> | ||
| <Menus | ||
| menus={[ | ||
| { | ||
| name: '짬뽕', | ||
| price: 20000, | ||
| isRecommended: false, | ||
| }, | ||
| { | ||
| name: '짬뽕', | ||
| price: 20000, | ||
| isRecommended: false, | ||
| }, | ||
| { | ||
| name: '짬뽕', | ||
| price: 20000, | ||
| isRecommended: false, | ||
| }, | ||
| { | ||
| name: '짬뽕', | ||
| price: 20000, | ||
| isRecommended: false, | ||
| }, | ||
| { | ||
| name: '짬뽕', | ||
| price: 20000, | ||
| isRecommended: false, | ||
| }, | ||
| { | ||
| name: '짬뽕', | ||
| price: 20000, | ||
| isRecommended: false, | ||
| }, | ||
| ]} | ||
| /> | ||
| <Description | ||
| description={ | ||
| '직원이 엄청 친절해요! 👍🏻\n' + | ||
| '근데 화장실에 좁고 냄새나요 ㅠㅠ\n' + | ||
| '그래도 짬뽕 양도 많고 불맛 나서 괜춘' | ||
| } | ||
| /> | ||
| <ActionButtonGroup onOpen={onOpen} /> | ||
| </Column> | ||
| </VerticalScrollArea> | ||
| <RejectModal isOpen={isOpen} onOpenChange={onOpenChange} /> | ||
| </> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import type { IconType } from '@repo/ui/components/Icon' | ||
| import { Coord } from '../_utils/toLatLng' | ||
|
|
||
| type Photo = { photoId: string; photoUrl: string; displayOrder: number } | ||
|
|
||
| type Menu = { name: string; price: number; isRecommended: boolean } | ||
|
|
||
| type Category = { | ||
| id: string | ||
| name: string | ||
| iconKey: IconType | ||
| } | ||
|
|
||
| type Tag = { | ||
| id: string | ||
| name: string | ||
| iconKey: IconType | ||
| } | ||
|
|
||
| export type RequestDetail = { | ||
| placeId: string | ||
| placeName: string | ||
| requestDate: string | ||
| photos: Photo[] | ||
| address: string | ||
| location: Coord | ||
| description: string | ||
| menus: Menu[] | ||
| categories: Category[] | ||
| tags: Tag[] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { Flex } from '@repo/ui/components/Layout' | ||
| import { cn } from '@repo/ui/utils/cn' | ||
| import { COLOR_VARIANTS } from '@repo/ui/consts/colorVariant' | ||
|
|
||
| type Props = { | ||
| onOpen: VoidFunction | ||
| } | ||
|
|
||
| export const ActionButtonGroup = ({ onOpen }: Props) => ( | ||
| <Flex className={'gap-10'}> | ||
| <button | ||
| onClick={onOpen} | ||
| className={cn( | ||
| 'w-full', | ||
| 'rounded-lg', | ||
| 'py-2', | ||
| COLOR_VARIANTS.red.text, | ||
| COLOR_VARIANTS.red.background, | ||
| )} | ||
| > | ||
| 거절 | ||
| </button> | ||
| <button | ||
| className={cn( | ||
| 'w-full', | ||
| 'rounded-lg', | ||
| 'py-2', | ||
| COLOR_VARIANTS.blue.text, | ||
| COLOR_VARIANTS.blue.background, | ||
| )} | ||
| > | ||
| 등록 | ||
| </button> | ||
| </Flex> | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { ActionButtonGroup } from './ActionButtonGroup' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { Column } from '@repo/ui/components/Layout' | ||
| import { Chip } from '@repo/ui/components/Chip' | ||
| import { Text } from '@repo/ui/components/Text' | ||
| import { RequestDetail } from '../../_api/types' | ||
|
|
||
| type Props = { | ||
| description: RequestDetail['description'] | ||
| } | ||
|
|
||
| export const Description = ({ description }: Props) => { | ||
| return ( | ||
| <Column className={'gap-1.5'}> | ||
| <Text>소개</Text> | ||
| <Text variant={'body2'} className={'whitespace-pre-wrap'}> | ||
| {description} | ||
| </Text> | ||
| <div> | ||
| <Chip icon={'calculator'} label={'가성비 좋은'} /> | ||
| </div> | ||
| </Column> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { Description } from './Description' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
환경 변수 누락 시 처리 검증 필요
NEXT_PUBLIC_NAVER_MAP_ID가 설정되지 않은 경우 빈 문자열이 전달됩니다. Naver Maps API가 빈 문자열을 허용하는지, 아니면 런타임 오류가 발생할 수 있는지 확인하세요. 필요한 경우 환경 변수가 누락되었을 때 경고를 표시하거나 에러를 던지는 것을 고려하세요.다음 스크립트로 환경 변수 설정을 확인할 수 있습니다:
🏁 Script executed:
Length of output: 148
다음 스크립트로 코드와
.env*파일에서NEXT_PUBLIC_NAVER_MAP_ID사용 및 정의 여부를 확인하세요.🏁 Script executed:
Length of output: 550
환경 변수 필수 설정 및 누락 처리
현재
process.env.NEXT_PUBLIC_NAVER_MAP_ID가.env*에 정의되어 있지 않아 빈 문자열이 기본값으로 할당됩니다. 빌드/배포 환경에서 반드시 해당 변수를 설정하도록 보장하거나, 누락 시 예외를 던지거나 명확한 에러 메시지를 표시하도록 처리하세요.🤖 Prompt for AI Agents