style: run prettier on entire codebase
This commit is contained in:
@@ -1,111 +1,113 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useAlert } from '../context/AlertContext'
|
||||
import { useAuth } from '../context/AuthContext'
|
||||
import Forbidden from '../components/Forbidden'
|
||||
import { useNavigate, Link } from 'react-router-dom'
|
||||
import { motion } from 'framer-motion'
|
||||
import { useState, useEffect } from "react";
|
||||
import { useAlert } from "../context/AlertContext";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
import Forbidden from "../components/Forbidden";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import AdminDatePicker from '../components/AdminDatePicker'
|
||||
import FormField from '../components/FormField'
|
||||
import apiFetch from '../utils/api'
|
||||
const API_BASE = '/api/admin'
|
||||
import AdminDatePicker from "../components/AdminDatePicker";
|
||||
import FormField from "../components/FormField";
|
||||
import apiFetch from "../utils/api";
|
||||
const API_BASE = "/api/admin";
|
||||
|
||||
interface User {
|
||||
id: number | string
|
||||
name: string
|
||||
id: number | string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface CreateForm {
|
||||
user_id: string
|
||||
shift_date: string
|
||||
leave_type: string
|
||||
leave_hours: number
|
||||
arrival_date: string
|
||||
arrival_time: string
|
||||
break_start_date: string
|
||||
break_start_time: string
|
||||
break_end_date: string
|
||||
break_end_time: string
|
||||
departure_date: string
|
||||
departure_time: string
|
||||
notes: string
|
||||
user_id: string;
|
||||
shift_date: string;
|
||||
leave_type: string;
|
||||
leave_hours: number;
|
||||
arrival_date: string;
|
||||
arrival_time: string;
|
||||
break_start_date: string;
|
||||
break_start_time: string;
|
||||
break_end_date: string;
|
||||
break_end_time: string;
|
||||
departure_date: string;
|
||||
departure_time: string;
|
||||
notes: string;
|
||||
}
|
||||
|
||||
export default function AttendanceCreate() {
|
||||
const alert = useAlert()
|
||||
const { hasPermission } = useAuth()
|
||||
const navigate = useNavigate()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [users, setUsers] = useState<User[]>([])
|
||||
const alert = useAlert();
|
||||
const { hasPermission } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const today = new Date().toISOString().split("T")[0];
|
||||
|
||||
const [form, setForm] = useState<CreateForm>({
|
||||
user_id: '',
|
||||
user_id: "",
|
||||
shift_date: today,
|
||||
leave_type: 'work',
|
||||
leave_type: "work",
|
||||
leave_hours: 8,
|
||||
arrival_date: today,
|
||||
arrival_time: '',
|
||||
arrival_time: "",
|
||||
break_start_date: today,
|
||||
break_start_time: '',
|
||||
break_start_time: "",
|
||||
break_end_date: today,
|
||||
break_end_time: '',
|
||||
break_end_time: "",
|
||||
departure_date: today,
|
||||
departure_time: '',
|
||||
notes: ''
|
||||
})
|
||||
departure_time: "",
|
||||
notes: "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUsers = async () => {
|
||||
try {
|
||||
const response = await apiFetch(`${API_BASE}/users`)
|
||||
const result = await response.json()
|
||||
const response = await apiFetch(`${API_BASE}/users`);
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
setUsers(Array.isArray(result.data) ? result.data : result.data?.items || [])
|
||||
setUsers(
|
||||
Array.isArray(result.data) ? result.data : result.data?.items || [],
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
alert.error('Nepodařilo se načíst uživatele')
|
||||
alert.error("Nepodařilo se načíst uživatele");
|
||||
} finally {
|
||||
setLoading(false)
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchUsers()
|
||||
}, [alert])
|
||||
fetchUsers();
|
||||
}, [alert]);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
e.preventDefault();
|
||||
|
||||
if (!form.user_id || !form.shift_date) {
|
||||
alert.error('Vyplňte zaměstnance a datum směny')
|
||||
return
|
||||
alert.error("Vyplňte zaměstnance a datum směny");
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true)
|
||||
setSubmitting(true);
|
||||
|
||||
try {
|
||||
const response = await apiFetch(`${API_BASE}/attendance`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(form)
|
||||
})
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(form),
|
||||
});
|
||||
|
||||
const result = await response.json()
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
alert.success(result.message)
|
||||
navigate(`/attendance/admin?month=${form.shift_date.substring(0, 7)}`)
|
||||
alert.success(result.message);
|
||||
navigate(`/attendance/admin?month=${form.shift_date.substring(0, 7)}`);
|
||||
} else {
|
||||
alert.error(result.error)
|
||||
alert.error(result.error);
|
||||
}
|
||||
} catch {
|
||||
alert.error('Chyba připojení')
|
||||
alert.error("Chyba připojení");
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleShiftDateChange = (newDate: string) => {
|
||||
setForm({
|
||||
@@ -114,33 +116,42 @@ export default function AttendanceCreate() {
|
||||
arrival_date: newDate,
|
||||
break_start_date: newDate,
|
||||
break_end_date: newDate,
|
||||
departure_date: newDate
|
||||
})
|
||||
}
|
||||
departure_date: newDate,
|
||||
});
|
||||
};
|
||||
|
||||
const isWorkType = form.leave_type === 'work'
|
||||
const isWorkType = form.leave_type === "work";
|
||||
|
||||
if (!hasPermission('attendance.admin')) return <Forbidden />
|
||||
if (!hasPermission("attendance.admin")) return <Forbidden />;
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="admin-skeleton" style={{ padding: 0, gap: '1.5rem' }}>
|
||||
<div className="admin-skeleton-row" style={{ justifyContent: 'space-between' }}>
|
||||
<div className="admin-skeleton-line h-8" style={{ width: '200px' }} />
|
||||
<div className="admin-skeleton" style={{ padding: 0, gap: "1.5rem" }}>
|
||||
<div
|
||||
className="admin-skeleton-row"
|
||||
style={{ justifyContent: "space-between" }}
|
||||
>
|
||||
<div className="admin-skeleton-line h-8" style={{ width: "200px" }} />
|
||||
</div>
|
||||
<div className="admin-card" style={{ maxWidth: '600px' }}>
|
||||
<div className="admin-skeleton" style={{ gap: '1.25rem' }}>
|
||||
{[0, 1, 2, 3, 4].map(i => (
|
||||
<div className="admin-card" style={{ maxWidth: "600px" }}>
|
||||
<div className="admin-skeleton" style={{ gap: "1.25rem" }}>
|
||||
{[0, 1, 2, 3, 4].map((i) => (
|
||||
<div key={i}>
|
||||
<div className="admin-skeleton-line w-1/4" style={{ marginBottom: '0.5rem', height: '10px' }} />
|
||||
<div
|
||||
className="admin-skeleton-line w-1/4"
|
||||
style={{ marginBottom: "0.5rem", height: "10px" }}
|
||||
/>
|
||||
<div className="admin-skeleton-line w-full h-10" />
|
||||
</div>
|
||||
))}
|
||||
<div className="admin-skeleton-line h-10" style={{ width: '120px', borderRadius: '8px' }} />
|
||||
<div
|
||||
className="admin-skeleton-line h-10"
|
||||
style={{ width: "120px", borderRadius: "8px" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -155,7 +166,10 @@ export default function AttendanceCreate() {
|
||||
<h1 className="admin-page-title">Přidat záznam docházky</h1>
|
||||
</div>
|
||||
<div className="admin-page-actions">
|
||||
<Link to="/attendance/admin" className="admin-btn admin-btn-secondary">
|
||||
<Link
|
||||
to="/attendance/admin"
|
||||
className="admin-btn admin-btn-secondary"
|
||||
>
|
||||
← Zpět na správu
|
||||
</Link>
|
||||
</div>
|
||||
@@ -163,7 +177,7 @@ export default function AttendanceCreate() {
|
||||
|
||||
<motion.div
|
||||
className="admin-card"
|
||||
style={{ maxWidth: '600px' }}
|
||||
style={{ maxWidth: "600px" }}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.25, delay: 0.06 }}
|
||||
@@ -174,13 +188,17 @@ export default function AttendanceCreate() {
|
||||
<FormField label="Zaměstnanec" required>
|
||||
<select
|
||||
value={form.user_id}
|
||||
onChange={(e) => setForm({ ...form, user_id: e.target.value })}
|
||||
onChange={(e) =>
|
||||
setForm({ ...form, user_id: e.target.value })
|
||||
}
|
||||
className="admin-form-select"
|
||||
required
|
||||
>
|
||||
<option value="">Vyberte zaměstnance</option>
|
||||
{users.map((user) => (
|
||||
<option key={user.id} value={user.id}>{user.name}</option>
|
||||
<option key={user.id} value={user.id}>
|
||||
{user.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</FormField>
|
||||
@@ -197,7 +215,9 @@ export default function AttendanceCreate() {
|
||||
<FormField label="Typ záznamu" required>
|
||||
<select
|
||||
value={form.leave_type}
|
||||
onChange={(e) => setForm({ ...form, leave_type: e.target.value })}
|
||||
onChange={(e) =>
|
||||
setForm({ ...form, leave_type: e.target.value })
|
||||
}
|
||||
className="admin-form-select"
|
||||
>
|
||||
<option value="work">Práce</option>
|
||||
@@ -213,13 +233,20 @@ export default function AttendanceCreate() {
|
||||
<input
|
||||
type="number"
|
||||
value={form.leave_hours}
|
||||
onChange={(e) => setForm({ ...form, leave_hours: parseFloat(e.target.value) })}
|
||||
onChange={(e) =>
|
||||
setForm({
|
||||
...form,
|
||||
leave_hours: parseFloat(e.target.value),
|
||||
})
|
||||
}
|
||||
min="0.5"
|
||||
max="24"
|
||||
step="0.5"
|
||||
className="admin-form-input"
|
||||
/>
|
||||
<small className="admin-form-hint">Výchozí 8 hodin pro celý den</small>
|
||||
<small className="admin-form-hint">
|
||||
Výchozí 8 hodin pro celý den
|
||||
</small>
|
||||
</FormField>
|
||||
)}
|
||||
|
||||
@@ -230,14 +257,18 @@ export default function AttendanceCreate() {
|
||||
<AdminDatePicker
|
||||
mode="date"
|
||||
value={form.arrival_date}
|
||||
onChange={(val: string) => setForm({ ...form, arrival_date: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, arrival_date: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Příchod - čas">
|
||||
<AdminDatePicker
|
||||
mode="time"
|
||||
value={form.arrival_time}
|
||||
onChange={(val: string) => setForm({ ...form, arrival_time: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, arrival_time: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
@@ -247,14 +278,18 @@ export default function AttendanceCreate() {
|
||||
<AdminDatePicker
|
||||
mode="date"
|
||||
value={form.break_start_date}
|
||||
onChange={(val: string) => setForm({ ...form, break_start_date: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, break_start_date: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Začátek pauzy - čas">
|
||||
<AdminDatePicker
|
||||
mode="time"
|
||||
value={form.break_start_time}
|
||||
onChange={(val: string) => setForm({ ...form, break_start_time: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, break_start_time: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
@@ -264,14 +299,18 @@ export default function AttendanceCreate() {
|
||||
<AdminDatePicker
|
||||
mode="date"
|
||||
value={form.break_end_date}
|
||||
onChange={(val: string) => setForm({ ...form, break_end_date: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, break_end_date: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Konec pauzy - čas">
|
||||
<AdminDatePicker
|
||||
mode="time"
|
||||
value={form.break_end_time}
|
||||
onChange={(val: string) => setForm({ ...form, break_end_time: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, break_end_time: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
@@ -281,14 +320,18 @@ export default function AttendanceCreate() {
|
||||
<AdminDatePicker
|
||||
mode="date"
|
||||
value={form.departure_date}
|
||||
onChange={(val: string) => setForm({ ...form, departure_date: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, departure_date: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Odchod - čas">
|
||||
<AdminDatePicker
|
||||
mode="time"
|
||||
value={form.departure_time}
|
||||
onChange={(val: string) => setForm({ ...form, departure_time: val })}
|
||||
onChange={(val: string) =>
|
||||
setForm({ ...form, departure_time: val })
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
@@ -305,7 +348,10 @@ export default function AttendanceCreate() {
|
||||
</FormField>
|
||||
|
||||
<div className="admin-form-actions">
|
||||
<Link to="/attendance/admin" className="admin-btn admin-btn-secondary">
|
||||
<Link
|
||||
to="/attendance/admin"
|
||||
className="admin-btn admin-btn-secondary"
|
||||
>
|
||||
Zrušit
|
||||
</Link>
|
||||
<button
|
||||
@@ -313,12 +359,12 @@ export default function AttendanceCreate() {
|
||||
disabled={submitting}
|
||||
className="admin-btn admin-btn-primary"
|
||||
>
|
||||
{submitting ? 'Ukládám...' : 'Uložit'}
|
||||
{submitting ? "Ukládám..." : "Uložit"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user