Some checks failed
Deploy MyApp on Same Server / build-and-deploy (push) Has been cancelled
- Replace custom page layout with AppShell component for consistent UI - Remove unused PageHeader and UpdateAlertConditionDto imports - Update service worker cache names and version.json to new timestamp
170 lines
6.3 KiB
TypeScript
170 lines
6.3 KiB
TypeScript
"use client"
|
||
import { useEffect, useState } from 'react'
|
||
import { useRouter } from 'next/navigation'
|
||
import { api } from '@/lib/api'
|
||
import { Smartphone, ArrowLeft } from 'lucide-react'
|
||
import Loading from '@/components/Loading'
|
||
import { MobileInput } from '@/components/forms'
|
||
import { ErrorMessage } from '@/components/common'
|
||
import { getCurrentPersianYear, getCurrentPersianMonth, getCurrentPersianDay } from '@/lib/date/persian-date'
|
||
|
||
export default function Home() {
|
||
const router = useRouter()
|
||
const [mobile, setMobile] = useState('')
|
||
const [loading, setLoading] = useState(false)
|
||
const [error, setError] = useState<string | null>(null)
|
||
|
||
useEffect(() => {
|
||
// Check if user is logged in
|
||
const token = localStorage.getItem('authToken')
|
||
const userStr = localStorage.getItem('user')
|
||
|
||
if (token && userStr) {
|
||
try {
|
||
const user = JSON.parse(userStr)
|
||
|
||
// Try to use the saved device from localStorage first
|
||
const savedDeviceId = localStorage.getItem('selectedDeviceId')
|
||
if (savedDeviceId) {
|
||
const today = `${getCurrentPersianYear()}/${String(getCurrentPersianMonth()).padStart(2, '0')}/${String(getCurrentPersianDay()).padStart(2, '0')}`
|
||
router.push(`/daily-report?deviceId=${savedDeviceId}&date=${encodeURIComponent(today)}`)
|
||
return
|
||
}
|
||
|
||
// No saved device — fetch user devices and auto-select the first one
|
||
api.getUserDevices(user.id)
|
||
.then((devices) => {
|
||
if (devices.length > 0) {
|
||
const firstDevice = devices[0]
|
||
// Save to localStorage
|
||
localStorage.setItem('selectedDeviceId', String(firstDevice.id))
|
||
localStorage.setItem('selectedDeviceName', firstDevice.deviceName)
|
||
const today = `${getCurrentPersianYear()}/${String(getCurrentPersianMonth()).padStart(2, '0')}/${String(getCurrentPersianDay()).padStart(2, '0')}`
|
||
router.push(`/daily-report?deviceId=${firstDevice.id}&date=${encodeURIComponent(today)}`)
|
||
} else {
|
||
// No devices — go to devices page to show the error
|
||
router.push('/devices')
|
||
}
|
||
})
|
||
.catch(() => {
|
||
// On error, fall back to devices page
|
||
router.push('/devices')
|
||
})
|
||
} catch {
|
||
// Invalid user data, go to login
|
||
}
|
||
}
|
||
}, [router])
|
||
|
||
const normalizeMobile = (mobile: string): string => {
|
||
const digitsOnly = mobile.replace(/\D/g, '')
|
||
if (digitsOnly.startsWith('9') && digitsOnly.length === 10) {
|
||
return '0' + digitsOnly
|
||
}
|
||
if (digitsOnly.startsWith('0098') && digitsOnly.length === 13) {
|
||
return '0' + digitsOnly.substring(3)
|
||
}
|
||
if (digitsOnly.startsWith('98') && digitsOnly.length === 12) {
|
||
return '0' + digitsOnly.substring(2)
|
||
}
|
||
return digitsOnly
|
||
}
|
||
|
||
const handleSubmit = async (e: React.FormEvent) => {
|
||
e.preventDefault()
|
||
setError(null)
|
||
|
||
const normalizedMobile = normalizeMobile(mobile)
|
||
|
||
if (!normalizedMobile || normalizedMobile.length !== 11 || !normalizedMobile.startsWith('09')) {
|
||
setError('لطفاً شماره موبایل معتبر وارد کنید (مثال: 09123456789)')
|
||
return
|
||
}
|
||
|
||
setLoading(true)
|
||
|
||
try {
|
||
const result = await api.sendCode({ mobile: normalizedMobile })
|
||
|
||
if (result.success) {
|
||
// Redirect to verify page with mobile number
|
||
router.push(`/verify-code?mobile=${encodeURIComponent(normalizedMobile)}`)
|
||
return // Don't set loading to false — component will unmount
|
||
} else {
|
||
setError(result.message || 'خطا در ارسال کد')
|
||
}
|
||
} catch (error: unknown) {
|
||
console.error('Error sending code:', error)
|
||
setError(error instanceof Error ? error.message : 'خطا در ارتباط با سرور')
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
const canSubmit = mobile.length >= 10
|
||
|
||
if (loading) {
|
||
return <Loading message="در حال ارسال کد..." />
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center p-4">
|
||
<div className="w-full max-w-md">
|
||
<div className="bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
||
<div className="text-center mb-8">
|
||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl shadow-lg mb-4">
|
||
<Smartphone className="w-8 h-8 text-white" />
|
||
</div>
|
||
<h1 className="text-2xl font-bold text-gray-900 mb-2">
|
||
ورود با شماره موبایل
|
||
</h1>
|
||
<p className="text-sm text-gray-600">
|
||
شماره موبایل خود را وارد کنید تا کد فعالسازی برای شما ارسال شود
|
||
</p>
|
||
</div>
|
||
|
||
<form onSubmit={handleSubmit} className="space-y-5">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
شماره موبایل
|
||
</label>
|
||
<MobileInput
|
||
value={mobile}
|
||
onValueChange={(value) => {
|
||
setMobile(value)
|
||
setError(null)
|
||
}}
|
||
disabled={loading}
|
||
/>
|
||
</div>
|
||
|
||
{error && <ErrorMessage message={error} />}
|
||
|
||
<button
|
||
type="submit"
|
||
disabled={loading || !canSubmit}
|
||
className={`w-full py-3 rounded-xl text-white font-medium transition-all duration-200 flex items-center justify-center gap-2 shadow-md ${
|
||
!loading && canSubmit
|
||
? 'bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 hover:shadow-lg transform hover:-translate-y-0.5'
|
||
: 'bg-gray-300 cursor-not-allowed'
|
||
}`}
|
||
>
|
||
{loading ? (
|
||
<>
|
||
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
|
||
در حال ارسال...
|
||
</>
|
||
) : (
|
||
<>
|
||
ارسال کد فعالسازی
|
||
<ArrowLeft className="w-5 h-5" />
|
||
</>
|
||
)}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|