Initial commit
This commit is contained in:
100
frontend/src/pages/Leave.tsx
Normal file
100
frontend/src/pages/Leave.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { api } from '../lib/api';
|
||||
import { LeaveDto, LeaveType } from '../types';
|
||||
|
||||
const TYPES: LeaveType[] = ['ANNUAL', 'SICK', 'PERSONAL', 'MARRIAGE', 'MATERNITY', 'BEREAVEMENT'];
|
||||
|
||||
export default function Leave() {
|
||||
const [list, setList] = useState<LeaveDto[]>([]);
|
||||
const [type, setType] = useState<LeaveType>('ANNUAL');
|
||||
const [startTime, setStartTime] = useState('');
|
||||
const [endTime, setEndTime] = useState('');
|
||||
const [reason, setReason] = useState('');
|
||||
|
||||
const load = () => api.get<LeaveDto[]>('/leave-requests/my').then(setList);
|
||||
|
||||
useEffect(() => {
|
||||
load();
|
||||
}, []);
|
||||
|
||||
const submit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
await api.post('/leave-requests', {
|
||||
type,
|
||||
startTime: new Date(startTime).toISOString(),
|
||||
endTime: new Date(endTime).toISOString(),
|
||||
reason,
|
||||
});
|
||||
setReason('');
|
||||
setStartTime('');
|
||||
setEndTime('');
|
||||
load();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="page animate-in">
|
||||
<div className="page-header">
|
||||
<h1>请假</h1>
|
||||
<p>提交申请与查看记录</p>
|
||||
</div>
|
||||
|
||||
<div className="grid cols-2">
|
||||
<div className="card">
|
||||
<div className="card-title">提交请假</div>
|
||||
<form className="form" onSubmit={submit}>
|
||||
<label>
|
||||
类型
|
||||
<select value={type} onChange={(e) => setType(e.target.value as LeaveType)}>
|
||||
{TYPES.map((t) => (
|
||||
<option key={t} value={t}>
|
||||
{t}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
开始时间
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={startTime}
|
||||
onChange={(e) => setStartTime(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
结束时间
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={endTime}
|
||||
onChange={(e) => setEndTime(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
原因
|
||||
<textarea value={reason} onChange={(e) => setReason(e.target.value)} required />
|
||||
</label>
|
||||
<button className="btn btn-primary">提交</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<div className="card-title">我的请假</div>
|
||||
<div className="list-stagger">
|
||||
{list.map((l) => (
|
||||
<div key={l.id} className="list-item">
|
||||
<div className="list-title">
|
||||
{l.type} · {l.status}
|
||||
</div>
|
||||
<div className="list-sub">
|
||||
{new Date(l.startTime).toLocaleString()} → {new Date(l.endTime).toLocaleString()}
|
||||
</div>
|
||||
<div className="list-sub">{l.reason}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user