Skip to content

Commit

Permalink
[feat/#28] 스냅샷 저장 및 조회 기능 추가, 저장된 스냅샷이 있는 경우 해당 스냅샷 사용하도록
Browse files Browse the repository at this point in the history
  • Loading branch information
lkhoony committed Aug 25, 2024
1 parent 52c6cbb commit 0425693
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 31 deletions.
14 changes: 7 additions & 7 deletions src/api/axiosInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ const axiosInstance = axios.create({
// localStorage에서 토큰 가져오기
const token = localStorage.getItem("accessToken")
if (token) {
axiosInstance.defaults.headers.common["Authorization"] = `Bearer ${token}`
axiosInstance.defaults.headers.common["X-HERO-AUTH-TOKEN"] = token
}

// 엑세스 토큰 설정 함수
export const setAccessToken = (token: string) => {
axiosInstance.defaults.headers.common["Authorization"] = `Bearer ${token}`
localStorage.setItem("accessToken", token)
export const setAccessToken = (_token: string): void => {
axiosInstance.defaults.headers.common["X-HERO-AUTH-TOKEN"] = _token
// localStorage.setItem("accessToken", token)
}

// 엑세스 토큰 제거 함수
export const clearAccessToken = () => {
delete axiosInstance.defaults.headers.common["Authorization"]
localStorage.removeItem("accessToken")
export const clearAccessToken = (): void => {
delete axiosInstance.defaults.headers.common["X-HERO-AUTH-TOKEN"]
// localStorage.removeItem("accessToken")
}

export default axiosInstance
1 change: 1 addition & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./auth"
export * from "./snapshot"
64 changes: 64 additions & 0 deletions src/api/snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import axiosInstance from "./axiosInstance"

export type position =
| "NOSE"
| "LEFT_EYE"
| "RIGHT_EYE"
| "LEFT_EAR"
| "RIGHT_EAR"
| "LEFT_SHOULDER"
| "RIGHT_SHOULDER"
| "LEFT_ELBOW"
| "RIGHT_ELBOW"
| "LEFT_WRIST"
| "RIGHT_WRIST"
| "LEFT_HIP"
| "RIGHT_HIP"
| "LEFT_KNEE"
| "RIGHT_KNEE"
| "LEFT_ANKLE"
| "RIGHT_ANKLE"

export interface point {
position: position
x: number
y: number
}

export interface snapshot {
id?: number
points: point[]
}

export interface createSnapshotRes {
id: string
}

export const createSnapshot = async (snapshot: snapshot): Promise<createSnapshotRes> => {
try {
const res = await axiosInstance.post(`/pose-layouts`, { snapshot })
const { id } = res.data.data

return { id }
} catch (e) {
throw e
}
}

export const getSnapshots = async (id: string): Promise<snapshot> => {
try {
const res = await axiosInstance.get(`/pose-layouts/${id}`)
return res.data.data
} catch (e) {
throw e
}
}

export const getRecentSnapshot = async (): Promise<snapshot> => {
try {
const res = await axiosInstance.get(`/pose-layouts/recent`)
return res.data.data
} catch (e) {
throw e
}
}
35 changes: 35 additions & 0 deletions src/components/PoseDetector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { worker } from "@/utils/worker"
import { useCallback, useEffect, useRef, useState } from "react"
import Camera from "./Camera"
import GuidePopup from "./Posture/GuidePopup"
import { useSnapshotStore } from "@/store/SnapshotStore"
import { useCreateSnaphot } from "@/hooks/useSnapshotMutation"
import { position } from "@/api"

const PoseDetector: React.FC = () => {
const [isScriptLoaded, setIsScriptLoaded] = useState<boolean>(false)
Expand All @@ -23,6 +26,10 @@ const PoseDetector: React.FC = () => {
const timer = useRef<any>(null)
const canvasRef = useRef<HTMLCanvasElement>(null)

const snapshot = useSnapshotStore((state) => state.snapshot)
const createSnapMutation = useCreateSnaphot()
const setSnap = useSnapshotStore((state) => state.setSnapshot)

const { requestNotificationPermission, showNotification } = usePushNotification()

const requestApi = (delay: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, delay))
Expand Down Expand Up @@ -114,6 +121,30 @@ const PoseDetector: React.FC = () => {
const getInitSnap = (): void => {
if (modelRef && modelRef.current) {
snapRef.current = resultRef.current
if (snapshot === null) {
if (snapRef.current) {
const req = snapRef.current[0].keypoints.map((p) => ({
position: p.name.toUpperCase() as position,
x: p.x,
y: p.y,
}))
createSnapMutation.mutate(
{ points: req },
{
onSuccess: (data: any) => {
setSnap(data)
},
}
)
}
}
setIsSnapSaved(true)
}
}

const getUserSnap = (): void => {
if (snapshot) {
snapRef.current = [{ keypoints: snapshot }]
setIsSnapSaved(true)
}
}
Expand All @@ -137,6 +168,10 @@ const PoseDetector: React.FC = () => {
}
}, [isModelLoaded, detectStart])

useEffect(() => {
getUserSnap()
}, [snapshot])

// const initializePoseMonitoring = () => {
// setIsTextNeck(null)
// setSlope(null)
Expand Down
35 changes: 35 additions & 0 deletions src/hooks/useSnapshotMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createSnapshot, createSnapshotRes, getRecentSnapshot, getSnapshots, snapshot } from "@/api"
import { useMutation, UseMutationResult } from "@tanstack/react-query"

export const useCreateSnaphot = (): UseMutationResult<createSnapshotRes, unknown, snapshot, unknown> => {
return useMutation({
mutationFn: (snapshot: snapshot) => {
return createSnapshot(snapshot)
},
onSuccess: (data) => {
console.log(data)
},
})
}

export const useGetSnapshot = (): UseMutationResult<snapshot, unknown, string, unknown> => {
return useMutation({
mutationFn: (id: string) => {
return getSnapshots(id)
},
onSuccess: (data) => {
console.log(data)
},
})
}

export const useGetRecentSnapshot = (): UseMutationResult<snapshot, unknown, void, unknown> => {
return useMutation({
mutationFn: () => {
return getRecentSnapshot()
},
onSuccess: (data) => {
console.log(data)
},
})
}
12 changes: 12 additions & 0 deletions src/pages/AuthPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Login from "@/components/Login"
import { useOauth, useSignUp, useSignIn, useGetIsSignUp } from "@/hooks/useAuthMutation"
import RoutePath from "@/constants/routes.json"
import { useAuthStore } from "@/store/AuthStore"
import { useSnapshotStore } from "@/store/SnapshotStore"
import { useGetRecentSnapshot } from "@/hooks/useSnapshotMutation"

const AuthPage: React.FC = () => {
const navigate = useNavigate()
Expand All @@ -12,11 +14,13 @@ const AuthPage: React.FC = () => {
const getIsSignUpMutation = useGetIsSignUp()
const signUpMutation = useSignUp()
const signInMutation = useSignIn()
const getRecentSnapMutation = useGetRecentSnapshot()

const [isLoading, setIsLoading] = useState(true)
const [isError, setIsError] = useState(false)

const setUser = useAuthStore((state) => state.setUser)
const setSnap = useSnapshotStore((state) => state.setSnapshot)

useEffect(() => {
const authenticate = async (): Promise<void> => {
Expand All @@ -41,6 +45,14 @@ const AuthPage: React.FC = () => {
// AuthStore에 사용자 정보와 토큰 저장
setUser({ uid, nickname }, accessToken)

// 최근 스냅샷을 가져오기
const userSnap = await getRecentSnapMutation.mutateAsync()

// 스냅샷이 있으면 store에 저장
if (userSnap.id !== -1) {
setSnap(userSnap.points.map((p) => ({ name: p.position.toLocaleLowerCase(), x: p.x, y: p.y, confidence: 1 })))
}

setIsLoading(false)
navigate(RoutePath.MONITORING)
} catch (error) {
Expand Down
8 changes: 4 additions & 4 deletions src/routes/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { BrowserRouter, Route, Routes, Navigate } from "react-router-dom"
import { AuthPage, MonitoringPage, HomePage } from "@/pages"
import { Layout } from "@/layouts"
import RoutePath from "@/constants/routes.json"
// import AuthRoute from "@/routes/AuthRoute" // ToDo: 로그인 정상화 될때까지 routing 보호하지 않도록 수정
import AuthRoute from "@/routes/AuthRoute"

const Router: React.FC = () => {
return (
Expand All @@ -13,9 +13,9 @@ const Router: React.FC = () => {
<Route path="/" element={<HomePage />} />
<Route path="/" element={<Layout />}>
{/* AuthRoute로 보호된 경로를 감쌉니다 */}
{/* <Route element={<AuthRoute />}> */}
<Route path={RoutePath.MONITORING} element={<MonitoringPage />} />
{/* </Route> */}
<Route element={<AuthRoute />}>
<Route path={RoutePath.MONITORING} element={<MonitoringPage />} />
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Route>
</Routes>
Expand Down
12 changes: 12 additions & 0 deletions src/store/SnapshotStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { keypoint } from "@/utils"
import { create } from "zustand"

interface SnapshotState {
snapshot: keypoint[] | null
setSnapshot: (snapshot: keypoint[]) => void
}

export const useSnapshotStore = create<SnapshotState>((set) => ({
snapshot: null,
setSnapshot: (snapshot: keypoint[]) => set({ snapshot }),
}))
40 changes: 20 additions & 20 deletions src/utils/detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,26 @@ export interface box {
// 포즈 객체의 타입 정의
export interface pose {
keypoints: keypoint[]
box: box
score: number
id: number
nose: keypoint
left_eye: keypoint
right_eye: keypoint
left_ear: keypoint
right_ear: keypoint
left_shoulder: keypoint
right_shoulder: keypoint
left_elbow: keypoint
right_elbow: keypoint
left_wrist: keypoint
right_wrist: keypoint
left_hip: keypoint
right_hip: keypoint
left_knee: keypoint
right_knee: keypoint
left_ankle: keypoint
right_ankle: keypoint
box?: box
score?: number
id?: number
nose?: keypoint
left_eye?: keypoint
right_eye?: keypoint
left_ear?: keypoint
right_ear?: keypoint
left_shoulder?: keypoint
right_shoulder?: keypoint
left_elbow?: keypoint
right_elbow?: keypoint
left_wrist?: keypoint
right_wrist?: keypoint
left_hip?: keypoint
right_hip?: keypoint
left_knee?: keypoint
right_knee?: keypoint
left_ankle?: keypoint
right_ankle?: keypoint
}

/**
Expand Down

0 comments on commit 0425693

Please sign in to comment.