This commit is contained in:
@@ -34,17 +34,24 @@ services:
|
|||||||
frontend:
|
frontend:
|
||||||
image: 192.168.31.100:3847/arrelin/wedding-frontend:latest
|
image: 192.168.31.100:3847/arrelin/wedding-frontend:latest
|
||||||
container_name: wedding_frontend
|
container_name: wedding_frontend
|
||||||
expose:
|
|
||||||
- "80"
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
networks:
|
networks:
|
||||||
- app_network
|
- app_network
|
||||||
|
- coolify
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.http.routers.wedding-frontend.rule=Host(`weddinge.duckdns.org`)
|
||||||
|
- traefik.http.routers.wedding-frontend.entrypoints=https
|
||||||
|
- traefik.http.routers.wedding-frontend.tls=true
|
||||||
|
- traefik.http.services.wedding-frontend.loadbalancer.server.port=80
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
app_network:
|
app_network:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
coolify:
|
||||||
|
external: true
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|||||||
@@ -16,24 +16,24 @@ interface Response {
|
|||||||
export default function Admin() {
|
export default function Admin() {
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [authed, setAuthed] = useState(false)
|
const [authed, setAuthed] = useState(false)
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [responses, setResponses] = useState<Response[]>([])
|
const [responses, setResponses] = useState<Response[]>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
const handleLogin = async (e: React.FormEvent) => {
|
const handleLogin = async (e: React.FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setError(false)
|
setError(null)
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/api/admin/responses', {
|
const res = await fetch('/api/admin/responses', {
|
||||||
headers: { 'x-admin-password': password },
|
headers: { 'x-admin-password': password },
|
||||||
})
|
})
|
||||||
if (res.status === 401) { setError(true); return }
|
if (res.status === 401) { setError('Неверный пароль'); return }
|
||||||
if (!res.ok) throw new Error()
|
if (!res.ok) throw new Error(`Ошибка сервера: ${res.status}`)
|
||||||
setResponses(await res.json())
|
setResponses(await res.json())
|
||||||
setAuthed(true)
|
setAuthed(true)
|
||||||
} catch {
|
} catch (err) {
|
||||||
setError(true)
|
setError(err instanceof Error ? err.message : 'Не удалось подключиться к серверу')
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ export default function Admin() {
|
|||||||
onChange={e => setPassword(e.target.value)}
|
onChange={e => setPassword(e.target.value)}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{error && <p className="admin-gate-error">Неверный пароль</p>}
|
{error && <p className="admin-gate-error">{error}</p>}
|
||||||
<button className="admin-gate-btn" type="submit" disabled={loading}>
|
<button className="admin-gate-btn" type="submit" disabled={loading}>
|
||||||
{loading ? 'Загрузка...' : 'Войти'}
|
{loading ? 'Загрузка...' : 'Войти'}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user