remove existed code to protected/model

This commit is contained in:
Timofey
2025-08-29 14:09:35 +03:00
parent ffe77d1ce0
commit 9d604e8965
6 changed files with 195 additions and 58 deletions

View File

@@ -0,0 +1,60 @@
'use client'
import React, { useState } from 'react'
import ModelViewer from '@/components/ModelViewer'
export default function Home() {
const [modelInfo, setModelInfo] = useState<{
meshes: unknown[]
boundingBox: {
min: { x: number; y: number; z: number }
max: { x: number; y: number; z: number }
}
} | null>(null)
const [error, setError] = useState<string | null>(null)
const handleModelLoaded = (data: {
meshes: unknown[]
boundingBox: {
min: { x: number; y: number; z: number }
max: { x: number; y: number; z: number }
}
}) => {
setModelInfo(data)
setError(null)
console.log('Model loaded successfully:', data)
}
const handleError = (errorMessage: string) => {
setError(errorMessage)
setModelInfo(null)
}
return (
<div className="relative h-screen">
<ModelViewer
modelPath="/models/EXPO_АР_PostRecon_level.gltf"
onModelLoaded={handleModelLoaded}
onError={handleError}
/>
{error && (
<div className="absolute top-4 right-4 left-4 z-50 rounded-lg bg-red-600/90 p-4 text-sm text-white md:right-auto md:left-4 md:w-80">
<strong>Error:</strong> {error}
</div>
)}
{modelInfo && (
<div className="absolute top-4 right-4 z-50 max-w-xs rounded-lg bg-black/80 p-4 text-sm text-white">
<h3 className="mb-3 text-base font-semibold">EXPO Building Model</h3>
<div className="space-y-1 text-xs text-gray-300">
<div>🖱 Left click + drag: Rotate</div>
<div>🖱 Right click + drag: Pan</div>
<div>🖱 Scroll: Zoom in/out</div>
</div>
</div>
)}
</div>
)
}

1
frontend/app/default.ts Normal file
View File

@@ -0,0 +1 @@
export { redirect as default } from 'next/navigation'

View File

@@ -1,60 +1,5 @@
'use client' import { redirect } from 'next/navigation'
import React, { useState } from 'react'
import ModelViewer from '../components/ModelViewer'
export default function Home() { export default function Home() {
const [modelInfo, setModelInfo] = useState<{ redirect('/objects')
meshes: unknown[]
boundingBox: {
min: { x: number; y: number; z: number }
max: { x: number; y: number; z: number }
}
} | null>(null)
const [error, setError] = useState<string | null>(null)
const handleModelLoaded = (data: {
meshes: unknown[]
boundingBox: {
min: { x: number; y: number; z: number }
max: { x: number; y: number; z: number }
}
}) => {
setModelInfo(data)
setError(null)
console.log('Model loaded successfully:', data)
}
const handleError = (errorMessage: string) => {
setError(errorMessage)
setModelInfo(null)
}
return (
<div className="h-screen relative">
<ModelViewer
modelPath="/models/EXPO_АР_PostRecon_level.gltf"
onModelLoaded={handleModelLoaded}
onError={handleError}
/>
{error && (
<div className="absolute top-4 left-4 right-4 md:left-4 md:right-auto md:w-80 bg-red-600/90 text-white p-4 rounded-lg z-50 text-sm">
<strong>Error:</strong> {error}
</div>
)}
{modelInfo && (
<div className="absolute top-4 right-4 bg-black/80 text-white p-4 rounded-lg z-50 text-sm max-w-xs">
<h3 className="text-base font-semibold mb-3">EXPO Building Model</h3>
<div className="text-xs text-gray-300 space-y-1">
<div>🖱 Left click + drag: Rotate</div>
<div>🖱 Right click + drag: Pan</div>
<div>🖱 Scroll: Zoom in/out</div>
</div>
</div>
)}
</div>
)
} }

View File

@@ -0,0 +1,47 @@
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { User, UserState } from '../types'
interface UserStore extends UserState {
// состояние
isAuthenticated: boolean
user: User | null
// действия
setUser: (user: User | null) => void
setAuthenticated: (isAuthenticated: boolean) => void
logout: () => void
// асинхронные действия
//! что пользователь может делать асинхронно?
}
const useUserStore = create<UserStore>()(
persist(
set => ({
// начальное состояние
isAuthenticated: false,
user: null,
favorites: [],
// синхронные действия
setUser: user => set({ user }),
setAuthenticated: isAuthenticated => set({ isAuthenticated }),
logout: () =>
set({
isAuthenticated: false,
user: null,
}),
}),
//! асинхронщина?
{ name: 'user-store' }
)
)
export default useUserStore
// пример использования
// const { user, isAuthenticated } = useUserStore() -- получаем данные из стора
// const { setUser, setAuthenticated } = useUserStore() -- устанавливаем данные в стор
// const { logout } = useUserStore() -- выходим из пользовательского аккаунта

View File

@@ -7,3 +7,28 @@ export interface ValidationRules {
export interface ValidationErrors { export interface ValidationErrors {
[key: string]: string [key: string]: string
} }
export type ToastProps = {
type: 'error' | 'success' | 'loading'
message: string
action?: {
text: string
onClick: () => void
}
duration?: number
}
export interface User {
id?: number | undefined
name: string
surname: string
image?: string
email: string
account_type?: string
login: string
}
export interface UserState {
isAuthenticated: boolean
user: User | null
}

View File

@@ -0,0 +1,59 @@
import toast from 'react-hot-toast'
import { ToastProps } from '@/app/types'
const toastStyles = {
success: {
background: 'bg-green-50',
text: 'text-green-800',
border: 'border-green-200',
},
error: {
background: 'bg-red-50',
text: 'text-red-800',
border: 'border-red-200',
},
loading: {
background: 'bg-blue-50',
text: 'text-blue-800',
border: 'border-blue-200',
},
}
const showToast = ({ type, message, action, duration }: ToastProps) => {
const styles = toastStyles[type]
toast.custom(
t => (
<div
className={`${
t.visible ? 'animate-slideIn' : 'animate-slideOut'
} pointer-events-auto rounded-2xl px-3 shadow-lg ${styles.background} ${
styles.border
} transform border transition-all duration-300 ease-in-out`}
>
<div className="p-4">
<div className="flex items-start">
<div className="flex-1">
<p className={`text-sm font-medium ${styles.text}`}>{message}</p>
{action && (
<div className="text-center">
<button
onClick={action.onClick}
className="mt-2 text-sm font-medium text-red-600 hover:text-red-800"
>
{action.text}
</button>
</div>
)}
</div>
</div>
</div>
</div>
),
{ duration: duration || 4000 }
)
}
export default showToast
//пример использования: showToast({ type: 'error', message: 'Неверный email или пароль' })