Skip to content

Commit

Permalink
Merge pull request #16 from the-kingdoms/develop
Browse files Browse the repository at this point in the history
Feat: Develop
  • Loading branch information
DeveloperRyou authored Sep 3, 2024
2 parents c06d42f + e2a3052 commit 1cd0abc
Show file tree
Hide file tree
Showing 36 changed files with 1,407 additions and 647 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

.env
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"dayjs": "^1.11.12",
"dotenv": "^16.4.5",
"electron-is-dev": "^3.0.1",
"framer-motion": "^11.3.30",
"jotai": "^2.9.0",
"jotai-devtools": "^0.10.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-loading-indicators": "^1.0.0",
"react-router-dom": "^6.25.1",
"react-scripts": "5.0.1",
"styled-components": "^6.1.12",
"typescript": "^4.9.5",
"use-sound": "^4.0.3",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down Expand Up @@ -62,5 +66,6 @@
"electron": "^31.2.1",
"electron-builder": "^24.13.3",
"wait-on": "^7.2.0"
}
},
"packageManager": "[email protected]"
}
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>얼루가게 PC</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import Layout from './components/layout'
import Login from './pages/login'
import HistoryMain from './pages/history'
import WaitMain from './pages/waiting'
import Redirect from 'pages/oauth'

export default function App() {
return (
<Routes>
<Route path={ROUTE.LOGIN} element={<Login />} />
<Route path={ROUTE.OAUTH} element={<Redirect />} />
<Route element={<Layout />}>
<Route path={ROUTE.WAITING_MAIN} element={<WaitMain />} />
<Route path={ROUTE.PROCESS_MAIN} element={<ProcessMain />} />
Expand Down
18 changes: 18 additions & 0 deletions src/apis/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import api from './network'

interface PostLoginResponse {
token: string
}

export interface PostKakaoLoginBody {
code: string
state: string
redirectUri: string
}

async function postKakaoLogin(body: PostKakaoLoginBody): Promise<PostLoginResponse> {
const { data } = await api.post(`/api/login/kakao`, body)
return data
}

export { postKakaoLogin }
48 changes: 48 additions & 0 deletions src/apis/my.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import api from './network'

type RoleType = 'OWNER' | 'MANAGER' | 'STAFF'
type DayType = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday'

interface AbstractMember {
id: string | null
name: string | null
phone: string | null
providerType: 'KAKAO' | null
storeList: Store[]
}

interface My extends AbstractMember {
relationList: Relation[]
}

interface Relation {
id: string
storeId: string
member: AbstractMember
planList: Plan[]
role: RoleType
position: string
}

interface Plan {
id: string
relationId: string
day: DayType
startTime: string
endTime: string
restStartTime: string
restEndTime: string
}

interface Store {
storeId: string
name: string
}

async function getMy(): Promise<My> {
const { data } = await api.get<My>(`/api/my`)
return data
}

export { getMy }
export type { My }
42 changes: 42 additions & 0 deletions src/apis/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import axios from 'axios'

const setTokenFromLocalStorage = (access_token: string) => {
localStorage.setItem('access_token', access_token)
}

const getTokenFromLocalStorage = () => {
const accessToken = localStorage.getItem('access_token')
if (!accessToken) return null

return accessToken
}

const eollugageUrl = process.env.REACT_APP_API_URL

const api = axios.create({
baseURL: eollugageUrl,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
Accept: 'application/json',
'Access-Control-Allow-Origin': 'http://localhost:3000',
'Access-Control-Allow-Credentials': 'true',
},
validateStatus: status => {
return status < 300
},
})
api.interceptors.request.use(
async config => {
if (typeof document !== 'undefined') {
const token = getTokenFromLocalStorage()
config.headers.set('Authorization', `Bearer ${token}`)
}
return config
},
error => {
return Promise.reject(error)
},
)

export default api
export { setTokenFromLocalStorage, getTokenFromLocalStorage }
46 changes: 46 additions & 0 deletions src/apis/paymentHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import api from './network'

export interface PaymentHistory {
paymentHistoryId: string
storeId: string
tableNumber: number
status: PaymentHistoryStatus
paidAt: null
totalPrice: number
orderHistoryResponseDtoList: OrderHistory[]
}

export interface OrderHistory {
orderHistoryId: string
paymentHistoryId: string
orderDetail: string
totalPrice: number
createdAt: string
updatedAt: string | null
status: OrderHistoryStatus
}

type PaymentHistoryStatus = 'WAITING' | 'PROCESS' | 'HISTORY'
type OrderHistoryStatus = 'APPROVED' | 'PENDING' | 'DISAPPROVED' | 'HISTORY'

async function getPaymentHistory(storeId: string, status?: string, filter: string = 'ALL'): Promise<PaymentHistory[]> {
const statusQuery = status ? `&status=${status}` : ''
const { data } = await api.get(`/api/v1/stores/${storeId}/payment-histories?filter=${filter}${statusQuery}`)
return data
}

async function patchPaymentHistory(
storeId: string,
paymentHistoryId: string,
orderHistoryId: string,
status: string,
): Promise<PaymentHistory[]> {
const body = { status }
const { data } = await api.patch(
`/api/v1/stores/${storeId}/payment-histories/${paymentHistoryId}/order-histories/${orderHistoryId}`,
body,
)
return data
}

export { getPaymentHistory, patchPaymentHistory }
Binary file added src/assets/sound/newOrder.mp3
Binary file not shown.
41 changes: 22 additions & 19 deletions src/components/historyDateFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,49 @@
import dayjs from 'dayjs'
import React, { SetStateAction, useState } from 'react'
import React, { SetStateAction } from 'react'
import styled from 'styled-components'

const buttonText = ['오늘', '1주', '1개월']
const buttonText = [
{ label: '오늘', value: 'TODAY' },
{ label: '1주', value: 'WEEK' },
{ label: '1개월', value: 'MONTH' },
]

interface HistoryDateFilterProps {
date: string
setDate: React.Dispatch<SetStateAction<string>>
filter: string
setFilter: React.Dispatch<SetStateAction<string>>
}

export default function HistoryDateFilter({ date, setDate }: HistoryDateFilterProps) {
const [selectedIdx, setSelectedIdx] = useState<number>(0)

const onClickDate = (index: number) => {
setSelectedIdx(index)
switch (index) {
case 0:
export default function HistoryDateFilter({ date, setDate, filter, setFilter }: HistoryDateFilterProps) {
const onClickDate = (value: string) => {
switch (value) {
case 'TODAY':
setDate(dayjs().format('YYYY.MM.DD'))
setFilter('TODAY')
break
case 1:
case 'WEEK':
setDate(dayjs().subtract(1, 'week').format('YYYY.MM.DD') + ' - ' + dayjs().format('YYYY.MM.DD'))
setFilter('WEEK')
break
case 2:
case 'MONTH':
setDate(dayjs().subtract(1, 'month').format('YYYY.MM.DD') + ' - ' + dayjs().format('YYYY.MM.DD'))
setFilter('MONTH')
break
default:
setDate('error')
setFilter('ALL')
}
}

const onClickDateInput = (event: React.ChangeEvent<HTMLInputElement>) => {
setDate(dayjs(event.target.value).format('YYYY.MM.DD'))
}

return (
<Container>
{buttonText.map((text, i) => (
<DateButton selected={i === selectedIdx} onClick={() => onClickDate(i)}>
{text}
{buttonText.map((button, i) => (
<DateButton selected={button.value === filter} onClick={() => onClickDate(button.value)}>
{button.label}
</DateButton>
))}
<DateInput type="date" value={dayjs(date).format('YYYY.MM.DD')} onChange={onClickDateInput} />
<DateInput type="date" value={dayjs().format('YYYY-MM-DD')} defaultValue={dayjs().format('YYYY-MM-DD')} />
</Container>
)
}
Expand Down
30 changes: 30 additions & 0 deletions src/components/kakaoButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import styled from 'styled-components'
import { createRandomString } from 'utils/createRandomId'

export default function KakaoButton() {
const redirectUri = `${window.location.origin}/oauth`
const onClickLogin = () => {
window.location.href = `https://kauth.kakao.com/oauth/authorize?redirect_uri=${redirectUri}&client_id=${
process.env.REACT_APP_KAKAO_REST_KEY
}&response_type=code&state=${createRandomString(8)}`
}

return (
<KakaoLoginButton onClick={onClickLogin}>
<img src={require('assets/image/kakao.png')} width={24} height={24} alt="kakao-login-button" />
카카오 로그인
</KakaoLoginButton>
)
}

const KakaoLoginButton = styled.div`
background-color: #fee500;
width: 328px;
border-radius: 1000px;
padding: 20px 0;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
cursor: pointer;
`
20 changes: 17 additions & 3 deletions src/components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,34 @@ import { Outlet, useNavigate } from 'react-router'
import styled from 'styled-components'
import NavBar from './navBar'
import { useAtom } from 'jotai'
import { currentTabAtom, historyCountAtom, processCountAtom, waitingCountAtom } from 'utils/atom'
import { currentTabAtom, modalDetailAtom, modalShowAtom, processCountAtom, waitingCountAtom } from 'utils/atom'
import { ROUTE } from 'constants/path'
import Modal from './modal'

export default function Layout() {
const navigate = useNavigate()
const [, setCurrentTab] = useAtom(currentTabAtom)
const [waitingCount] = useAtom(waitingCountAtom)
const [processCount] = useAtom(processCountAtom)
const [historyCount] = useAtom(historyCountAtom)
const [modalDetail] = useAtom(modalDetailAtom)
const [modalShow] = useAtom(modalShowAtom)

const navBarItem = [
{
name: '승인 대기',
count: waitingCount,
label: ROUTE.WAITING_MAIN,
onClick: () => onClickTab(ROUTE.WAITING_MAIN),
},
{
name: '진행 중',
count: processCount,
label: ROUTE.PROCESS_MAIN,
onClick: () => onClickTab(ROUTE.PROCESS_MAIN),
},
{
name: '히스토리',
count: historyCount,
label: ROUTE.HISTORY_MAIN,
onClick: () => onClickTab(ROUTE.HISTORY_MAIN),
},
]
Expand All @@ -37,6 +41,16 @@ export default function Layout() {

return (
<Container>
{modalShow && (
<Modal
title={modalDetail?.title}
description={modalDetail?.description}
grayButtonText={modalDetail?.grayButtonText}
blackButtonText={modalDetail?.blackButtonText}
onClickGrayButton={modalDetail?.onClickGrayButton}
onClickBlackButton={modalDetail?.onClickBlackButton}
/>
)}
<NavWrapper>
<NavBar items={navBarItem} />
</NavWrapper>
Expand Down
Loading

0 comments on commit 1cd0abc

Please sign in to comment.