Revize 1865a0be
Přidáno uživatelem Pavel Fidransky před více než 4 roky(ů)
client/src/App.js | ||
---|---|---|
9 | 9 |
import Setting from './Setting'; |
10 | 10 |
import LogOut from './LogOut'; |
11 | 11 |
import Login from './Login'; |
12 |
import { BrowserRouter, Route, Switch } from "react-router-dom";
|
|
13 |
import * as api_fetch from './api'
|
|
12 |
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
|
13 |
import * as api from './api';
|
|
14 | 14 |
|
15 |
function App() { |
|
15 |
export default function App() {
|
|
16 | 16 |
|
17 | 17 |
useEffect(() => { |
18 | 18 |
if (window.location.pathname === '/login' || window.location.pathname === '/logout') return; |
19 | 19 |
|
20 |
api_fetch.getCurrentProfile().then(currentProfile => {
|
|
20 |
api.getCurrentProfile().then(currentProfile => { |
|
21 | 21 |
setCurrentUser(currentProfile); |
22 | 22 |
}).catch(reason => { |
23 |
alert(reason)
|
|
23 |
alert(reason);
|
|
24 | 24 |
}); |
25 | 25 |
}, []); |
26 | 26 |
|
... | ... | |
32 | 32 |
<div className="App"> |
33 | 33 |
<Nav currentUser={currentUser} /> |
34 | 34 |
<div className="container"> |
35 |
<Switch> |
|
36 |
<Route path="/" exact component={() => <Home currentUser={currentUser} setCurrentUser={setCurrentUser}/>}/> |
|
37 |
<Route path="/setting"> |
|
38 |
{currentUser !== undefined && currentUser.role === 'EMPLOYER' |
|
39 |
? |
|
40 |
<Setting/> |
|
41 |
: |
|
42 |
<div className="permissionText column"> |
|
43 |
<p>You don't have permission to access on this server.</p> |
|
44 |
</div> |
|
45 |
} |
|
46 |
</Route> |
|
47 |
<Route path="/logout"><LogOut/></Route> |
|
48 |
<Route path="/login"><Login/></Route> |
|
49 |
</Switch> |
|
35 |
<Switch> |
|
36 |
<Route path="/" exact component={() => <Home currentUser={currentUser} setCurrentUser={setCurrentUser}/>}/> |
|
37 |
<Route path="/setting"> |
|
38 |
{currentUser !== undefined && currentUser.role === 'EMPLOYER' ? ( |
|
39 |
<Setting/> |
|
40 |
) : ( |
|
41 |
<div className="permissionText column"> |
|
42 |
<p>You don't have permission to access on this server.</p> |
|
43 |
</div> |
|
44 |
)} |
|
45 |
</Route> |
|
46 |
<Route path="/logout"><LogOut/></Route> |
|
47 |
<Route path="/login"><Login/></Route> |
|
48 |
</Switch> |
|
50 | 49 |
</div> |
51 | 50 |
</div> |
52 | 51 |
</BrowserRouter> |
53 | 52 |
); |
54 | 53 |
} |
55 | 54 |
|
56 |
const Home = (props) => { |
|
57 |
const [user, setUser] = useState([]); |
|
58 |
|
|
55 |
function Home(props) { |
|
56 |
const [user, setUser] = useState({}); |
|
59 | 57 |
const [acceptedRequest, setAcceptedRequest] = useState([]); |
60 | 58 |
|
61 |
// OverviewAdmin state
|
|
59 |
// OverviewAdmin state |
|
62 | 60 |
const [employees, setEmployees] = useState([]); |
63 | 61 |
|
64 | 62 |
return ( |
65 | 63 |
<div className="container"> |
66 | 64 |
<div className="main-content"> |
67 |
{props.currentUser !== undefined && props.currentUser.role === 'EMPLOYER' |
|
68 |
? |
|
65 |
{props.currentUser !== undefined && props.currentUser.role === 'EMPLOYER' ? ( |
|
69 | 66 |
<UpcomingRequests user={user} setUser={setUser} acceptedRequest={acceptedRequest} setAcceptedRequest={setAcceptedRequest} setEmployees={setEmployees}/> |
70 |
:
|
|
67 |
) : (
|
|
71 | 68 |
<YourRequests user={user} setUser={setUser} acceptedRequest={acceptedRequest} setAcceptedRequest={setAcceptedRequest} currentUser={props.currentUser}/> |
72 |
} |
|
73 |
<Calendar setUser={setUser} user={user} acceptedRequest={acceptedRequest} setAcceptedRequest={setAcceptedRequest} currentUser={props.currentUser} setEmployees={setEmployees} setCurrentUser={props.setCurrentUser}/>
|
|
69 |
)}
|
|
70 |
<Calendar setUser={setUser} user={user} acceptedRequest={acceptedRequest} setAcceptedRequest={setAcceptedRequest} currentUser={props.currentUser} setEmployees={setEmployees} setCurrentUser={props.setCurrentUser}/> |
|
74 | 71 |
</div> |
75 |
{props.currentUser !== undefined && props.currentUser.role === 'EMPLOYER' |
|
76 |
? |
|
72 |
{props.currentUser !== undefined && props.currentUser.role === 'EMPLOYER' ? ( |
|
77 | 73 |
<OverviewAdmin employees={employees} setEmployees={setEmployees} /> |
78 |
:
|
|
79 |
<Overview currentUser={props.currentUser} employees={employees} />
|
|
80 |
} |
|
74 |
) : (
|
|
75 |
<Overview currentUser={props.currentUser} employees={employees} /> |
|
76 |
)}
|
|
81 | 77 |
</div> |
82 |
) |
|
83 |
}; |
|
84 |
|
|
85 |
export default App; |
|
86 |
|
|
78 |
); |
|
79 |
} |
client/src/Calendar.js | ||
---|---|---|
1 | 1 |
import React, { useState, useEffect } from 'react'; |
2 | 2 |
import './App.css'; |
3 |
import FullCalendar from '@fullcalendar/react' |
|
4 |
import dayGridPlugin from '@fullcalendar/daygrid' |
|
5 |
import '@fullcalendar/core/main.css' |
|
6 |
import '@fullcalendar/daygrid/main.css' |
|
3 |
import FullCalendar from '@fullcalendar/react';
|
|
4 |
import dayGridPlugin from '@fullcalendar/daygrid';
|
|
5 |
import '@fullcalendar/core/main.css';
|
|
6 |
import '@fullcalendar/daygrid/main.css';
|
|
7 | 7 |
import interactionPlugin from '@fullcalendar/interaction'; |
8 |
import Popup from "reactjs-popup";
|
|
8 |
import Popup from 'reactjs-popup';
|
|
9 | 9 |
import moment from 'moment'; |
10 |
import * as api_fetch from './api' |
|
11 |
|
|
12 |
|
|
13 |
function Calendar(props) { |
|
14 |
|
|
15 |
useEffect( () => { |
|
16 |
if (props.currentUser !== undefined) { |
|
17 |
props.currentUser.role === 'EMPLOYER' |
|
18 |
? |
|
19 |
api_fetch.getAdminCalendar().then(adminCalendar => { |
|
20 |
props.setAcceptedRequest(adminCalendar); |
|
21 |
}).catch(reason => { |
|
22 |
alert(reason) |
|
23 |
}) |
|
24 |
: |
|
25 |
api_fetch.getUserCalendar(props.currentUser, convertedDate).then(userCalendar => { |
|
26 |
props.setAcceptedRequest(userCalendar); |
|
27 |
}).catch(reason => { |
|
28 |
alert(reason) |
|
29 |
}); |
|
30 |
} |
|
31 |
}, [props.currentUser]); |
|
32 |
|
|
33 |
//states |
|
34 |
const [isOpen, setOpen] = useState(false) |
|
35 |
|
|
36 |
const [whatDate, setDate] = useState('') |
|
10 |
import * as api from './api'; |
|
37 | 11 |
|
38 |
const [whatTime, setWhatTime] = useState(7.5) |
|
12 |
const DEFAULT_MANDAY_HOURS = 7.5; |
|
13 |
const SICK_DAY_COUNT_INCREMENT = 1; |
|
39 | 14 |
|
40 |
const [typeRadio, setType] = useState('sickday')
|
|
15 |
export default function Calendar(props) {
|
|
41 | 16 |
|
42 |
var today = new Date(); |
|
43 |
|
|
44 |
// setting date to right format |
|
45 |
today = today.toISOString().split('T')[0] |
|
46 |
const convertedDate = today.split("-").join("/") |
|
17 |
useEffect(() => { |
|
18 |
if (props.currentUser === undefined) { |
|
19 |
return; |
|
20 |
} |
|
47 | 21 |
|
48 |
// ********************* ADD EVENT - EMPLOYEE ************************** |
|
22 |
if (props.currentUser.role === 'EMPLOYER') { |
|
23 |
api.getAdminCalendar().then(adminCalendar => { |
|
24 |
props.setAcceptedRequest(adminCalendar); |
|
25 |
}).catch(reason => { |
|
26 |
alert(reason); |
|
27 |
}); |
|
28 |
} else { |
|
29 |
api.getUserCalendar(props.currentUser, convertedDate).then(userCalendar => { |
|
30 |
props.setAcceptedRequest(userCalendar); |
|
31 |
}).catch(reason => { |
|
32 |
alert(reason); |
|
33 |
}); |
|
34 |
} |
|
35 |
}, [props.currentUser]); |
|
49 | 36 |
|
50 |
const addEvent = async (e) => { |
|
51 |
e.preventDefault(); |
|
52 |
|
|
53 |
try { |
|
54 |
// setting an object |
|
55 |
const newDate = whatDate.split("-").join("/"); |
|
37 |
//states |
|
38 |
const [isOpen, setOpen] = useState(false); |
|
39 |
const [whatDate, setDate] = useState(''); |
|
40 |
const [whatTime, setWhatTime] = useState(DEFAULT_MANDAY_HOURS); |
|
41 |
const [typeRadio, setType] = useState('sickday'); |
|
56 | 42 |
|
57 |
const dataAddEventEmployee = { |
|
58 |
type: typeRadio === 'sickday' ? 'SICK_DAY' : 'VACATION', |
|
59 |
date: newDate, |
|
60 |
from: typeRadio === 'sickday' ? null : "00:00", |
|
61 |
to: typeRadio === 'sickday' ? null : moment().startOf('day').add(whatTime, "hours").format("hh:mm"), |
|
62 |
} |
|
43 |
var today = new Date(); |
|
63 | 44 |
|
64 |
await api_fetch.addEventApi(dataAddEventEmployee); |
|
65 |
if (typeRadio === 'holiday') { |
|
66 |
props.setCurrentUser({ |
|
67 |
...props.currentUser, |
|
68 |
holiday: props.currentUser.holiday - whatTime |
|
69 |
}) |
|
70 |
} else if (typeRadio === 'sickday') { |
|
71 |
props.setCurrentUser({ |
|
72 |
...props.currentUser, |
|
73 |
takenSickday: props.currentUser.takenSickday + 1 |
|
74 |
}) |
|
45 |
// setting date to right format |
|
46 |
today = today.toISOString().split('T')[0]; |
|
47 |
const convertedDate = today.split('-').join('/'); |
|
48 |
|
|
49 |
// ********************* ADD EVENT - EMPLOYEE ************************** |
|
50 |
|
|
51 |
async function addEvent(e) { |
|
52 |
e.preventDefault(); |
|
53 |
|
|
54 |
try { |
|
55 |
// setting an object |
|
56 |
const newDate = whatDate.split('-').join('/'); |
|
57 |
|
|
58 |
const dataAddEventEmployee = { |
|
59 |
type: typeRadio === 'sickday' ? 'SICK_DAY' : 'VACATION', |
|
60 |
date: newDate, |
|
61 |
from: typeRadio === 'sickday' ? null : '00:00', |
|
62 |
to: typeRadio === 'sickday' ? null : moment().startOf('day').add(whatTime, 'hours').format('hh:mm'), |
|
63 |
}; |
|
64 |
|
|
65 |
await api.addEventApi(dataAddEventEmployee); |
|
66 |
|
|
67 |
if (typeRadio === 'holiday') { |
|
68 |
props.setCurrentUser({ |
|
69 |
...props.currentUser, |
|
70 |
holiday: props.currentUser.holiday - whatTime, |
|
71 |
}); |
|
72 |
} else if (typeRadio === 'sickday') { |
|
73 |
props.setCurrentUser({ |
|
74 |
...props.currentUser, |
|
75 |
takenSickday: props.currentUser.takenSickday + SICK_DAY_COUNT_INCREMENT, |
|
76 |
}); |
|
77 |
} |
|
78 |
|
|
79 |
setOpen(false); |
|
80 |
} catch (e) { |
|
81 |
alert(e); |
|
75 | 82 |
} |
76 |
|
|
77 |
setOpen(false) |
|
78 |
} catch (e) { |
|
79 |
alert(e) |
|
80 | 83 |
} |
81 |
} |
|
82 |
// ********************* ADD EVENT ADMIN - EMPLOYER ************************** |
|
83 | 84 |
|
84 |
const addEventAdmin = async (e) => { |
|
85 |
e.preventDefault(); |
|
85 |
// ********************* ADD EVENT ADMIN - EMPLOYER ************************** |
|
86 | 86 |
|
87 |
// setting an object
|
|
88 |
const newDate = whatDate.split("-").join("/");
|
|
87 |
async function addEventAdmin(e) {
|
|
88 |
e.preventDefault();
|
|
89 | 89 |
|
90 |
const dataAddEventAdmin = { |
|
91 |
type: typeRadio === 'sickday' ? 'SICK_DAY' : 'VACATION', |
|
92 |
date: newDate, |
|
93 |
from: typeRadio === 'sickday' ? null : "00:00", |
|
94 |
to: typeRadio === 'sickday' ? null : moment().startOf('day').add(whatTime, "hours").format("hh:mm"), |
|
95 |
}; |
|
90 |
// setting an object |
|
91 |
const newDate = whatDate.split('-').join('/'); |
|
96 | 92 |
|
97 |
api_fetch.addEventApiAdmin(dataAddEventAdmin).then(() => { |
|
98 |
const userProps = { |
|
99 |
title: props.currentUser.name, |
|
100 |
start: whatDate |
|
101 |
} |
|
102 |
//concat new request to current ones |
|
103 |
props.setAcceptedRequest((acceptedRequest) => acceptedRequest.concat(userProps)) |
|
104 |
}).catch(reason => { |
|
105 |
alert(reason) |
|
106 |
}); |
|
93 |
const dataAddEventAdmin = { |
|
94 |
type: typeRadio === 'sickday' ? 'SICK_DAY' : 'VACATION', |
|
95 |
date: newDate, |
|
96 |
from: typeRadio === 'sickday' ? null : '00:00', |
|
97 |
to: typeRadio === 'sickday' ? null : moment().startOf('day').add(whatTime, 'hours').format('hh:mm'), |
|
98 |
}; |
|
107 | 99 |
|
108 |
setOpen(false) |
|
100 |
api.addEventApiAdmin(dataAddEventAdmin).then(() => { |
|
101 |
const userProps = { |
|
102 |
title: props.currentUser.name, |
|
103 |
start: whatDate, |
|
104 |
}; |
|
105 |
//concat new request to current ones |
|
106 |
props.setAcceptedRequest((acceptedRequest) => acceptedRequest.concat(userProps)); |
|
107 |
}).catch(reason => { |
|
108 |
alert(reason); |
|
109 |
}); |
|
110 |
|
|
111 |
setOpen(false); |
|
109 | 112 |
|
110 |
api_fetch.getUsersOverview().then(usersOverview => {
|
|
111 |
props.setEmployees(usersOverview); |
|
113 |
api.getUsersOverview().then(usersOverview => {
|
|
114 |
props.setEmployees(usersOverview);
|
|
112 | 115 |
}).catch(reason => { |
113 |
alert(reason)
|
|
114 |
}); |
|
115 |
} |
|
116 |
alert(reason);
|
|
117 |
});
|
|
118 |
}
|
|
116 | 119 |
|
117 |
const DEFAULT_MANDAY_HOURS = 7.5; |
|
118 |
|
|
119 |
|
|
120 | 120 |
return ( |
121 | 121 |
<div className="calendar"> |
122 |
|
|
123 |
<FullCalendar defaultView="dayGridMonth" plugins={[ dayGridPlugin, interactionPlugin ]} |
|
124 |
|
|
125 |
dateClick={function(info) { |
|
126 |
setOpen(info.dateStr > today) |
|
127 |
setDate(info.dateStr) |
|
128 |
setWhatTime(DEFAULT_MANDAY_HOURS) |
|
129 |
}} |
|
130 |
events={[ |
|
131 |
...props.acceptedRequest |
|
132 |
]} |
|
133 |
/> |
|
134 |
|
|
135 |
<Popup |
|
136 |
open={isOpen} |
|
137 |
position="right center" |
|
138 |
modal |
|
139 |
closeOnDocumentClick |
|
140 |
onClose={() => setOpen(false)} |
|
141 |
> |
|
142 |
<div className="calendar-form"> |
|
143 |
<form onSubmit={props.currentUser !== undefined && props.currentUser.role === 'EMPLOYER' |
|
144 |
? (e) => addEventAdmin(e) |
|
145 |
: (e) => addEvent(e) |
|
146 |
}> |
|
147 |
<h2>Choose vacation type</h2> |
|
148 |
<div className="calendar-radio"> |
|
149 |
<input checked={ |
|
150 |
typeRadio === 'sickday' ? 'checked' : null} |
|
151 |
onChange={() => setType(typeRadio === 'holiday' ? 'sickday' : 'holiday')} |
|
152 |
type="radio" id="sickday" name="radiobutton" value="sickday" |
|
153 |
/> |
|
154 |
<label for="sickday">Sickday</label> |
|
155 |
</div> |
|
156 |
<div className="calendar-radio"> |
|
157 |
<input checked={ |
|
158 |
typeRadio === 'holiday' ? 'checked' : null} |
|
159 |
onChange={() => setType(typeRadio === 'holiday' ? 'sickday' : 'holiday')} |
|
160 |
type="radio" id="holiday" name="radiobutton" value="holiday" |
|
161 |
/> |
|
162 |
<label for="holiday">Extra Holiday</label> |
|
122 |
<FullCalendar |
|
123 |
defaultView="dayGridMonth" |
|
124 |
plugins={[dayGridPlugin, interactionPlugin]} |
|
125 |
dateClick={function(info) { |
|
126 |
setOpen(info.dateStr > today); |
|
127 |
setDate(info.dateStr); |
|
128 |
setWhatTime(DEFAULT_MANDAY_HOURS); |
|
129 |
}} |
|
130 |
events={[ |
|
131 |
...props.acceptedRequest, |
|
132 |
]}/> |
|
133 |
|
|
134 |
<Popup |
|
135 |
open={isOpen} |
|
136 |
position="right center" |
|
137 |
modal |
|
138 |
closeOnDocumentClick |
|
139 |
onClose={() => setOpen(false)} |
|
140 |
> |
|
141 |
<div className="calendar-form"> |
|
142 |
<form onSubmit={props.currentUser !== undefined && props.currentUser.role === 'EMPLOYER' ? (e) => addEventAdmin(e) : (e) => addEvent(e)}> |
|
143 |
<h2>Choose vacation type</h2> |
|
144 |
<div className="calendar-radio"> |
|
145 |
<input checked={typeRadio === 'sickday' ? 'checked' : null} |
|
146 |
onChange={() => setType(typeRadio === 'holiday' ? 'sickday' : 'holiday')} |
|
147 |
type="radio" id="sickday" name="radiobutton" value="sickday" |
|
148 |
/> |
|
149 |
<label htmlFor="sickday">Sickday</label> |
|
150 |
</div> |
|
151 |
<div className="calendar-radio"> |
|
152 |
<input checked={typeRadio === 'holiday' ? 'checked' : null} |
|
153 |
onChange={() => setType(typeRadio === 'holiday' ? 'sickday' : 'holiday')} |
|
154 |
type="radio" id="holiday" name="radiobutton" value="holiday" |
|
155 |
/> |
|
156 |
<label htmlFor="holiday">Extra Holiday</label> |
|
157 |
</div> |
|
158 |
<div> |
|
159 |
{typeRadio === 'holiday' ? <h4>Date & Hours</h4> : <h4>Date</h4>} |
|
160 |
<div className="row calendarInputs"> |
|
161 |
<input |
|
162 |
className="date-input" |
|
163 |
type='date' onChange={(e) => setDate(e.target.value)} |
|
164 |
value={whatDate} min={today} |
|
165 |
/> |
|
166 |
{typeRadio === 'holiday' ? ( |
|
167 |
<input |
|
168 |
className="input-time" |
|
169 |
step={0.5} |
|
170 |
min={0.5} |
|
171 |
max={7.5} |
|
172 |
type="number" |
|
173 |
onChange={(e) => setWhatTime(e.target.value)} |
|
174 |
required |
|
175 |
value={whatTime}/> |
|
176 |
) : null} |
|
177 |
</div> |
|
178 |
</div> |
|
179 |
<button className="btn btn-submit" type="submit">Request vacation</button> |
|
180 |
</form> |
|
163 | 181 |
</div> |
164 |
<div> |
|
165 |
{typeRadio === 'holiday' ? <h4>Date & Hours</h4> : <h4>Date</h4>} |
|
166 |
<div className="row calendarInputs"> |
|
167 |
<input |
|
168 |
className="date-input" |
|
169 |
type='date' onChange={(e) => setDate(e.target.value)} |
|
170 |
value={whatDate} min={today} |
|
171 |
/> |
|
172 |
{typeRadio === 'holiday' ? |
|
173 |
<input |
|
174 |
className="input-time" |
|
175 |
step={0.5} |
|
176 |
min={0.5} |
|
177 |
max={7.5} |
|
178 |
type="number" |
|
179 |
onChange={(e) => setWhatTime(e.target.value)} |
|
180 |
required |
|
181 |
value={whatTime} |
|
182 |
/> : null} |
|
183 |
</div> |
|
184 |
</div> |
|
185 |
<button className="btn btn-submit" type="submit">Request vacation</button> |
|
186 |
</form> |
|
187 |
</div> |
|
188 |
</Popup> |
|
189 |
|
|
182 |
</Popup> |
|
190 | 183 |
</div> |
191 | 184 |
); |
192 |
} |
|
193 |
|
|
194 |
|
|
195 |
export default Calendar; |
|
185 |
} |
client/src/HttpStatus.js | ||
---|---|---|
1 |
export const CONTINUE = 100; |
|
2 |
export const SWITCHING_PROTOCOLS = 101; |
|
3 |
export const PROCESSING = 102; |
|
4 |
export const OK = 200; |
|
5 |
export const CREATED = 201; |
|
6 |
export const ACCEPTED = 202; |
|
7 |
export const NON_AUTHORITATIVE_INFORMATION = 203; |
|
8 |
export const NO_CONTENT = 204; |
|
9 |
export const RESET_CONTENT = 205; |
|
10 |
export const PARTIAL_CONTENT = 206; |
|
11 |
export const MULTI_STATUS = 207; |
|
12 |
export const MULTIPLE_CHOICES = 300; |
|
13 |
export const MOVED_PERMANENTLY = 301; |
|
14 |
export const MOVED_TEMPORARILY = 302; |
|
15 |
export const SEE_OTHER = 303; |
|
16 |
export const NOT_MODIFIED = 304; |
|
17 |
export const USE_PROXY = 305; |
|
18 |
export const TEMPORARY_REDIRECT = 307; |
|
19 |
export const PERMANENT_REDIRECT = 308; |
|
20 |
export const BAD_REQUEST = 400; |
|
21 |
export const UNAUTHORIZED = 401; |
|
22 |
export const PAYMENT_REQUIRED = 402; |
|
23 |
export const FORBIDDEN = 403; |
|
24 |
export const NOT_FOUND = 404; |
|
25 |
export const METHOD_NOT_ALLOWED = 405; |
|
26 |
export const NOT_ACCEPTABLE = 406; |
|
27 |
export const PROXY_AUTHENTICATION_REQUIRED = 407; |
|
28 |
export const REQUEST_TIMEOUT = 408; |
|
29 |
export const CONFLICT = 409; |
|
30 |
export const GONE = 410; |
|
31 |
export const LENGTH_REQUIRED = 411; |
|
32 |
export const PRECONDITION_FAILED = 412; |
|
33 |
export const REQUEST_TOO_LONG = 413; |
|
34 |
export const REQUEST_URI_TOO_LONG = 414; |
|
35 |
export const UNSUPPORTED_MEDIA_TYPE = 415; |
|
36 |
export const REQUESTED_RANGE_NOT_SATISFIABLE = 416; |
|
37 |
export const EXPECTATION_FAILED = 417; |
|
38 |
export const IM_A_TEAPOT = 418; |
|
39 |
export const INSUFFICIENT_SPACE_ON_RESOURCE = 419; |
|
40 |
export const METHOD_FAILURE = 420; |
|
41 |
export const UNPROCESSABLE_ENTITY = 422; |
|
42 |
export const LOCKED = 423; |
|
43 |
export const FAILED_DEPENDENCY = 424; |
|
44 |
export const PRECONDITION_REQUIRED = 428; |
|
45 |
export const TOO_MANY_REQUESTS = 429; |
|
46 |
export const REQUEST_HEADER_FIELDS_TOO_LARGE = 431; |
|
47 |
export const INTERNAL_SERVER_ERROR = 500; |
|
48 |
export const NOT_IMPLEMENTED = 501; |
|
49 |
export const BAD_GATEWAY = 502; |
|
50 |
export const SERVICE_UNAVAILABLE = 503; |
|
51 |
export const GATEWAY_TIMEOUT = 504; |
|
52 |
export const HTTP_VERSION_NOT_SUPPORTED = 505; |
|
53 |
export const INSUFFICIENT_STORAGE = 507; |
|
54 |
export const NETWORK_AUTHENTICATION_REQUIRED = 511; |
client/src/LogOut.js | ||
---|---|---|
2 | 2 |
import './App.css'; |
3 | 3 |
|
4 | 4 |
function LogOut() { |
5 |
|
|
6 | 5 |
return ( |
7 | 6 |
<div className="login-container logout column"> |
8 | 7 |
<p>You have been successfully logged out!</p> |
9 | 8 |
</div> |
10 |
) |
|
9 |
);
|
|
11 | 10 |
} |
12 | 11 |
|
13 | 12 |
export default LogOut; |
client/src/Login.js | ||
---|---|---|
1 | 1 |
import React from 'react'; |
2 | 2 |
import './App.css'; |
3 | 3 |
|
4 |
|
|
5 |
function Login() { |
|
4 |
export default function Login() { |
|
6 | 5 |
return ( |
7 |
<div className="login-container column">
|
|
6 |
<div className="login-container column"> |
|
8 | 7 |
<a href={window.config.baseUrl + '/login/google?target=' + window.config.redirectUrl}><p>log in</p></a> |
9 | 8 |
</div> |
10 |
) |
|
9 |
);
|
|
11 | 10 |
} |
12 |
|
|
13 |
export default Login; |
client/src/Nav.js | ||
---|---|---|
1 | 1 |
import React from 'react'; |
2 | 2 |
import './App.css'; |
3 | 3 |
import { Link } from 'react-router-dom'; |
4 |
import * as api_fetch from './api'
|
|
4 |
import * as api from './api';
|
|
5 | 5 |
|
6 |
function Nav(props) { |
|
7 |
return ( |
|
8 |
props.currentUser === undefined |
|
9 |
? |
|
6 |
export default function Nav(props) { |
|
7 |
if (props.currentUser === undefined) { |
|
8 |
return ( |
|
10 | 9 |
<nav className="top-nav"> |
11 | 10 |
<Link className="link-nav" to="/login"><h1>YOSO</h1></Link> |
12 | 11 |
</nav> |
13 |
: |
|
14 |
<nav className="top-nav"> |
|
15 |
<Link className="link-nav" to="/"><h1>YOSO</h1></Link> |
|
16 |
<div className="profile-comp"> |
|
17 |
<img src={props.currentUser.photo} className="img-avatar" alt="profile_photo"></img> |
|
18 |
<h2>{props.currentUser.name}</h2> |
|
19 |
<ul> |
|
20 |
{props.currentUser.role === 'EMPLOYER' ? |
|
21 |
<li> |
|
22 |
<Link to="/setting"> |
|
23 |
<svg className="bi bi-gear-fill navIcon" width="20px" height="20px" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> |
|
24 |
<path fillRule="evenodd" d="M8.837 1.626c-.246-.835-1.428-.835-1.674 0l-.094.319A1.873 1.873 0 0 1 4.377 3.06l-.292-.16c-.764-.415-1.6.42-1.184 1.185l.159.292a1.873 1.873 0 0 1-1.115 2.692l-.319.094c-.835.246-.835 1.428 0 1.674l.319.094a1.873 1.873 0 0 1 1.115 2.693l-.16.291c-.415.764.42 1.6 1.185 1.184l.292-.159a1.873 1.873 0 0 1 2.692 1.116l.094.318c.246.835 1.428.835 1.674 0l.094-.319a1.873 1.873 0 0 1 2.693-1.115l.291.16c.764.415 1.6-.42 1.184-1.185l-.159-.291a1.873 1.873 0 0 1 1.116-2.693l.318-.094c.835-.246.835-1.428 0-1.674l-.319-.094a1.873 1.873 0 0 1-1.115-2.692l.16-.292c.415-.764-.42-1.6-1.185-1.184l-.291.159A1.873 1.873 0 0 1 8.93 1.945l-.094-.319zm-2.633-.283c.527-1.79 3.065-1.79 3.592 0l.094.319a.873.873 0 0 0 1.255.52l.292-.16c1.64-.892 3.434.901 2.54 2.541l-.159.292a.873.873 0 0 0 .52 1.255l.319.094c1.79.527 1.79 3.065 0 3.592l-.319.094a.873.873 0 0 0-.52 1.255l.16.292c.893 1.64-.902 3.434-2.541 2.54l-.292-.159a.873.873 0 0 0-1.255.52l-.094.319c-.527 1.79-3.065 1.79-3.592 0l-.094-.319a.873.873 0 0 0-1.255-.52l-.292.16c-1.64.893-3.433-.902-2.54-2.541l.159-.292a.873.873 0 0 0-.52-1.255l-.319-.094c-1.79-.527-1.79-3.065 0-3.592l.319-.094a.873.873 0 0 0 .52-1.255l-.16-.292c-.892-1.64.902-3.433 2.541-2.54l.292.159a.873.873 0 0 0 1.255-.52l.094-.319z"/> |
|
25 |
<path fillRule="evenodd" d="M8 5.754a2.246 2.246 0 1 0 0 4.492 2.246 2.246 0 0 0 0-4.492zM4.754 8a3.246 3.246 0 1 1 6.492 0 3.246 3.246 0 0 1-6.492 0z"/> |
|
26 |
</svg> |
|
27 |
</Link> |
|
28 |
</li> |
|
29 |
: null } |
|
30 |
<li> |
|
31 |
<button className="btn-logout" onClick={() => api_fetch.logOut()}> |
|
32 |
<svg className="bi bi-power navIcon" width="20px" height="20px" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> |
|
33 |
<path fillRule="evenodd" d="M5.578 4.437a5 5 0 1 0 4.922.044l.5-.866a6 6 0 1 1-5.908-.053l.486.875z"/> |
|
34 |
<path fillRule="evenodd" d="M7.5 8V1h1v7h-1z"/> |
|
35 |
</svg> |
|
36 |
</button> |
|
37 |
</li> |
|
38 |
</ul> |
|
39 |
</div> |
|
40 |
</nav> |
|
41 |
) |
|
42 |
} |
|
12 |
); |
|
13 |
} |
|
43 | 14 |
|
44 |
|
|
45 |
export default Nav; |
|
15 |
return ( |
|
16 |
<nav className="top-nav"> |
|
17 |
<Link className="link-nav" to="/"><h1>YOSO</h1></Link> |
|
18 |
<div className="profile-comp"> |
|
19 |
<img src={props.currentUser.photo} className="img-avatar" alt="profile_photo"></img> |
|
20 |
<h2>{props.currentUser.name}</h2> |
|
21 |
<ul> |
|
22 |
{props.currentUser.role === 'EMPLOYER' ? ( |
|
23 |
<li> |
|
24 |
<Link to="/setting"> |
|
25 |
<svg className="bi bi-gear-fill navIcon" width="20px" height="20px" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> |
|
26 |
<path fillRule="evenodd" d="M8.837 1.626c-.246-.835-1.428-.835-1.674 0l-.094.319A1.873 1.873 0 0 1 4.377 3.06l-.292-.16c-.764-.415-1.6.42-1.184 1.185l.159.292a1.873 1.873 0 0 1-1.115 2.692l-.319.094c-.835.246-.835 1.428 0 1.674l.319.094a1.873 1.873 0 0 1 1.115 2.693l-.16.291c-.415.764.42 1.6 1.185 1.184l.292-.159a1.873 1.873 0 0 1 2.692 1.116l.094.318c.246.835 1.428.835 1.674 0l.094-.319a1.873 1.873 0 0 1 2.693-1.115l.291.16c.764.415 1.6-.42 1.184-1.185l-.159-.291a1.873 1.873 0 0 1 1.116-2.693l.318-.094c.835-.246.835-1.428 0-1.674l-.319-.094a1.873 1.873 0 0 1-1.115-2.692l.16-.292c.415-.764-.42-1.6-1.185-1.184l-.291.159A1.873 1.873 0 0 1 8.93 1.945l-.094-.319zm-2.633-.283c.527-1.79 3.065-1.79 3.592 0l.094.319a.873.873 0 0 0 1.255.52l.292-.16c1.64-.892 3.434.901 2.54 2.541l-.159.292a.873.873 0 0 0 .52 1.255l.319.094c1.79.527 1.79 3.065 0 3.592l-.319.094a.873.873 0 0 0-.52 1.255l.16.292c.893 1.64-.902 3.434-2.541 2.54l-.292-.159a.873.873 0 0 0-1.255.52l-.094.319c-.527 1.79-3.065 1.79-3.592 0l-.094-.319a.873.873 0 0 0-1.255-.52l-.292.16c-1.64.893-3.433-.902-2.54-2.541l.159-.292a.873.873 0 0 0-.52-1.255l-.319-.094c-1.79-.527-1.79-3.065 0-3.592l.319-.094a.873.873 0 0 0 .52-1.255l-.16-.292c-.892-1.64.902-3.433 2.541-2.54l.292.159a.873.873 0 0 0 1.255-.52l.094-.319z"/> |
|
27 |
<path fillRule="evenodd" d="M8 5.754a2.246 2.246 0 1 0 0 4.492 2.246 2.246 0 0 0 0-4.492zM4.754 8a3.246 3.246 0 1 1 6.492 0 3.246 3.246 0 0 1-6.492 0z"/> |
|
28 |
</svg> |
|
29 |
</Link> |
|
30 |
</li> |
|
31 |
) : null} |
|
32 |
<li> |
|
33 |
<button className="btn-logout" onClick={() => api.logOut()}> |
|
34 |
<svg className="bi bi-power navIcon" width="20px" height="20px" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> |
|
35 |
<path fillRule="evenodd" d="M5.578 4.437a5 5 0 1 0 4.922.044l.5-.866a6 6 0 1 1-5.908-.053l.486.875z"/> |
|
36 |
<path fillRule="evenodd" d="M7.5 8V1h1v7h-1z"/> |
|
37 |
</svg> |
|
38 |
</button> |
|
39 |
</li> |
|
40 |
</ul> |
|
41 |
</div> |
|
42 |
</nav> |
|
43 |
); |
|
44 |
} |
client/src/Overview.js | ||
---|---|---|
1 | 1 |
import React from 'react'; |
2 | 2 |
import './App.css'; |
3 | 3 |
|
4 |
export default function OffsAvailable(props) { |
|
4 | 5 |
|
5 |
const OffsAvailable = (props) => { |
|
6 |
if (props.currentUser === undefined) { |
|
7 |
return null; |
|
8 |
} |
|
6 | 9 |
|
7 |
return props.currentUser === undefined ? null : (
|
|
8 |
<div>
|
|
9 |
<div className="side-content">
|
|
10 |
<div className="side-board column">
|
|
11 |
<div className="side-board-heading row">
|
|
12 |
<h3>Overview</h3>
|
|
13 |
</div>
|
|
14 |
<div className="underline-1"></div>
|
|
15 |
<div className="side-board-items column">
|
|
16 |
<table border = "0">
|
|
17 |
<tbody>
|
|
18 |
<tr>
|
|
19 |
<th className="th-left">Name</th>
|
|
20 |
<th>Sick Days</th>
|
|
21 |
<th>Holiday</th>
|
|
22 |
</tr>
|
|
23 |
<tr>
|
|
24 |
<td>{props.currentUser.name}</td>
|
|
25 |
<td className="td-center">{props.currentUser.takenSickday + '/' + props.currentUser.sickday}</td>
|
|
26 |
<td className="td-center">{props.currentUser.holiday}</td>
|
|
27 |
</tr>
|
|
28 |
</tbody>
|
|
29 |
</table>
|
|
30 |
</div>
|
|
31 |
</div>
|
|
10 |
return (
|
|
11 |
<div> |
|
12 |
<div className="side-content"> |
|
13 |
<div className="side-board column"> |
|
14 |
<div className="side-board-heading row"> |
|
15 |
<h3>Overview</h3> |
|
16 |
</div> |
|
17 |
<div className="underline-1"></div> |
|
18 |
<div className="side-board-items column"> |
|
19 |
<table border = "0"> |
|
20 |
<tbody> |
|
21 |
<tr> |
|
22 |
<th className="th-left">Name</th> |
|
23 |
<th>Sick Days</th> |
|
24 |
<th>Holiday</th> |
|
25 |
</tr>
|
|
26 |
<tr> |
|
27 |
<td>{props.currentUser.name}</td> |
|
28 |
<td className="td-center">{props.currentUser.takenSickday + '/' + props.currentUser.sickday}</td> |
|
29 |
<td className="td-center">{props.currentUser.holiday}</td> |
|
30 |
</tr> |
|
31 |
</tbody> |
|
32 |
</table> |
|
33 |
</div> |
|
34 |
</div> |
|
32 | 35 |
</div> |
33 |
</div> |
|
34 |
);
|
|
36 |
</div>
|
|
37 |
); |
|
35 | 38 |
} |
36 |
|
|
37 |
|
|
38 |
export default OffsAvailable; |
client/src/OverviewAdmin.js | ||
---|---|---|
1 | 1 |
import React, { useState, useEffect } from 'react'; |
2 | 2 |
import './App.css'; |
3 |
import * as api_fetch from './api'
|
|
3 |
import * as api from './api';
|
|
4 | 4 |
|
5 |
export default function OverviewAdmin(props) { |
|
5 | 6 |
|
6 |
const OverviewAdmin = (props) => { |
|
7 |
useEffect(() => { |
|
8 |
api.getUsersOverview().then(usersOverview => { |
|
9 |
props.setEmployees(usersOverview); |
|
10 |
}).catch(reason => { |
|
11 |
alert(reason); |
|
12 |
}); |
|
13 |
}, []); |
|
7 | 14 |
|
8 |
useEffect(() => { |
|
9 |
api_fetch.getUsersOverview().then(usersOverview => { |
|
10 |
props.setEmployees(usersOverview); |
|
11 |
}).catch(reason => { |
|
12 |
alert(reason) |
|
13 |
}); |
|
14 |
}, []); |
|
15 |
const [isEdit, setEdit] = useState(false); |
|
16 |
const [editedUserId, setEditedUserId] = useState(); |
|
17 |
const [prevEdit, setPrevEdit] = useState(); |
|
15 | 18 |
|
16 |
const [isEdit, setEdit] = useState(false); |
|
17 |
const [editedUserId, setEditedUserId] = useState(); |
|
18 |
const [prevEdit, setPrevEdit] = useState(); |
|
19 |
|
|
19 |
// functions |
|
20 |
function changeSickdays(newValue) { |
|
21 |
const newEmployees = props.employees.map(employee => { |
|
22 |
if (editedUserId === employee.id) { |
|
23 |
return { |
|
24 |
...employee, |
|
25 |
sickday: newValue, |
|
26 |
}; |
|
27 |
} else { |
|
28 |
return employee; |
|
29 |
} |
|
30 |
}); |
|
31 |
props.setEmployees(newEmployees); |
|
32 |
} |
|
33 |
|
|
34 |
function changeHoliday(newValue) { |
|
35 |
const newEmployees = props.employees.map(employee => { |
|
36 |
if (editedUserId === employee.id) { |
|
37 |
return { |
|
38 |
...employee, |
|
39 |
holiday: newValue, |
|
40 |
}; |
|
41 |
} else { |
|
42 |
return employee; |
|
43 |
} |
|
44 |
}); |
|
45 |
props.setEmployees(newEmployees); |
|
46 |
} |
|
20 | 47 |
|
21 |
// functions |
|
22 |
function changeSickdays(newValue) { |
|
23 |
const newEmployees = props.employees.map(employee => { |
|
24 |
if (editedUserId === employee.id) { |
|
25 |
return { |
|
26 |
...employee, |
|
27 |
sickday: newValue, |
|
28 |
}; |
|
29 |
} else { |
|
30 |
return employee |
|
31 |
} |
|
32 |
}) |
|
33 |
props.setEmployees(newEmployees); |
|
34 |
} |
|
48 |
async function submitEdit(e) { |
|
49 |
setEdit(isEdit === true ? false : true); |
|
50 |
setPrevEdit(props.employees); |
|
51 |
e.preventDefault(); |
|
35 | 52 |
|
36 |
function changeHoliday(newValue) { |
|
37 |
const newEmployees = props.employees.map(employee => { |
|
38 |
if (editedUserId === employee.id) { |
|
39 |
return { |
|
40 |
...employee, |
|
41 |
holiday: newValue, |
|
42 |
}; |
|
43 |
} else { |
|
44 |
return employee |
|
45 |
} |
|
46 |
}) |
|
47 |
props.setEmployees(newEmployees); |
|
48 |
} |
|
53 |
const found = props.employees.find(employee => editedUserId === employee.id); |
|
54 |
const foundPrevEdit = prevEdit.find(employee => editedUserId === employee.id); |
|
49 | 55 |
|
50 |
const submitEdit = async (e) => { |
|
51 |
|
|
52 |
setEdit(isEdit === true ? false : true); |
|
53 |
setPrevEdit(props.employees); |
|
54 |
e.preventDefault(); |
|
56 |
const dataOverviewObject = { |
|
57 |
id: found.id, |
|
58 |
vacationCount: Number(found.holiday) - foundPrevEdit.holiday, |
|
59 |
sickDayCount: Number(found.sickday), |
|
60 |
role: found.role, |
|
61 |
}; |
|
55 | 62 |
|
56 |
const found = props.employees.find(employee => editedUserId === employee.id); |
|
57 |
const foundPrevEdit = prevEdit.find(employee => editedUserId === employee.id); |
|
63 |
api.saveDataOverview(dataOverviewObject).catch(reason => { |
|
64 |
alert(reason); |
|
65 |
}); |
|
66 |
} |
|
58 | 67 |
|
59 |
const dataOverviewObject = { |
|
60 |
id: found.id, |
|
61 |
vacationCount: Number(found.holiday) - foundPrevEdit.holiday, |
|
62 |
sickDayCount: Number(found.sickday), |
|
63 |
role: found.role |
|
64 |
} |
|
68 |
function cancel() { |
|
69 |
props.setEmployees(prevEdit); |
|
70 |
setEdit(false); |
|
71 |
} |
|
65 | 72 |
|
66 |
api_fetch.saveDataOverview(dataOverviewObject).catch(reason => { |
|
67 |
alert(reason) |
|
68 |
}); |
|
69 |
} |
|
73 |
// ***** overview button ****** |
|
70 | 74 |
|
71 |
const cancel = () => {
|
|
72 |
props.setEmployees(prevEdit)
|
|
73 |
setEdit(false)
|
|
74 |
}
|
|
75 |
function editEmployee(employeeId, e) {
|
|
76 |
setEdit(true);
|
|
77 |
setEditedUserId(employeeId);
|
|
78 |
setPrevEdit(props.employees);
|
|
75 | 79 |
|
76 |
// ***** overview button ****** |
|
80 |
e.preventDefault(); |
|
81 |
} |
|
77 | 82 |
|
78 |
const editEmployee = (employeeId, e) => { |
|
79 |
setEdit(true) |
|
80 |
setEditedUserId(employeeId) |
|
81 |
setPrevEdit(props.employees) |
|
82 |
|
|
83 |
e.preventDefault(); |
|
84 |
} |
|
85 |
|
|
86 |
return ( |
|
87 |
<div> |
|
83 |
return ( |
|
84 |
<div> |
|
88 | 85 |
<div className="side-content"> |
89 |
<div className="side-board column">
|
|
90 |
<form className="column side-board-items" onSubmit={(e) => submitEdit(e)}>
|
|
86 |
<div className="side-board column"> |
|
87 |
<form className="column side-board-items" onSubmit={(e) => submitEdit(e)}> |
|
91 | 88 |
<div className="side-board-heading row"> |
92 |
<h3>Overview</h3>
|
|
89 |
<h3>Overview</h3> |
|
93 | 90 |
</div> |
94 | 91 |
<div className="underline-1"></div> |
95 | 92 |
<div className="side-board-items column"> |
96 |
<table className="side-board-table" border = "0">
|
|
97 |
<tbody> |
|
98 |
<tr> |
|
99 |
<th className="th-left">Name</th> |
|
100 |
<th>Sick Days</th> |
|
101 |
<th>Holiday</th> |
|
102 |
<th></th> |
|
103 |
</tr> |
|
93 |
<table className="side-board-table" border = "0"> |
|
94 |
<tbody>
|
|
95 |
<tr>
|
|
96 |
<th className="th-left">Name</th>
|
|
97 |
<th>Sick Days</th>
|
|
98 |
<th>Holiday</th>
|
|
99 |
<th></th>
|
|
100 |
</tr>
|
|
104 | 101 |
{props.employees.map(employee => ( |
105 |
<tr>
|
|
106 |
<td>{employee.name}</td> |
|
107 |
{/* SickDays Input */} |
|
108 |
<td className="td-center"> |
|
109 |
{isEdit === true && editedUserId === employee.id ? ( |
|
110 |
<input className="offsInput" type="number" min="0" value={employee.sickday} onChange={(e) => changeSickdays(e.target.value)}/> |
|
111 |
) : ( |
|
112 |
employee.takenSickday + '/' + employee.sickday |
|
113 |
)} |
|
114 |
</td> |
|
115 |
{/* Holiday Input */} |
|
116 |
<td className="td-center"> |
|
117 |
{isEdit === true && editedUserId === employee.id ? ( |
|
118 |
<input className="offsInput" type="number" min="0" value={employee.holiday} onChange={(e) => changeHoliday(e.target.value)}/> |
|
119 |
) : ( |
|
120 |
employee.holiday |
|
121 |
)}</td> |
|
122 |
<td> |
|
123 |
{/* Edit Button */} |
|
124 |
<button onClick={(e) => editEmployee(employee.id, e)} className="btn-edit"> |
|
125 |
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
126 |
<path fill-rule="evenodd" d="M11.293 1.293a1 1 0 0 1 1.414 0l2 2a1 1 0 0 1 0 1.414l-9 9a1 1 0 0 1-.39.242l-3 1a1 1 0 0 1-1.266-1.265l1-3a1 1 0 0 1 .242-.391l9-9zM12 2l2 2-9 9-3 1 1-3 9-9z"/>
|
|
127 |
<path fill-rule="evenodd" d="M12.146 6.354l-2.5-2.5.708-.708 2.5 2.5-.707.708zM3 10v.5a.5.5 0 0 0 .5.5H4v.5a.5.5 0 0 0 .5.5H5v.5a.5.5 0 0 0 .5.5H6v-1.5a.5.5 0 0 0-.5-.5H5v-.5a.5.5 0 0 0-.5-.5H3z"/>
|
|
128 |
</svg> |
|
129 |
</button> |
|
130 |
{/* End of Edit Button */} |
|
131 |
</td> |
|
132 |
</tr> |
|
102 |
<tr key={employee.id}>
|
|
103 |
<td>{employee.name}</td>
|
|
104 |
{/* SickDays Input */}
|
|
105 |
<td className="td-center">
|
|
106 |
{isEdit === true && editedUserId === employee.id ? (
|
|
107 |
<input className="offsInput" type="number" min="0" value={employee.sickday} onChange={(e) => changeSickdays(e.target.value)}/>
|
|
108 |
) : (
|
|
109 |
employee.takenSickday + '/' + employee.sickday
|
|
110 |
)}
|
|
111 |
</td>
|
|
112 |
{/* Holiday Input */}
|
|
113 |
<td className="td-center">
|
|
114 |
{isEdit === true && editedUserId === employee.id ? (
|
|
115 |
<input className="offsInput" type="number" min="0" value={employee.holiday} onChange={(e) => changeHoliday(e.target.value)}/>
|
|
116 |
) : (
|
|
117 |
employee.holiday
|
|
118 |
)}</td>
|
|
119 |
<td>
|
|
120 |
{/* Edit Button */}
|
|
121 |
<button onClick={(e) => editEmployee(employee.id, e)} className="btn-edit">
|
|
122 |
<svg width="1em" height="1em" viewBox="0 0 16 16" className="bi bi-pencil" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
123 |
<path fillRule="evenodd" d="M11.293 1.293a1 1 0 0 1 1.414 0l2 2a1 1 0 0 1 0 1.414l-9 9a1 1 0 0 1-.39.242l-3 1a1 1 0 0 1-1.266-1.265l1-3a1 1 0 0 1 .242-.391l9-9zM12 2l2 2-9 9-3 1 1-3 9-9z"/>
|
|
124 |
<path fillRule="evenodd" d="M12.146 6.354l-2.5-2.5.708-.708 2.5 2.5-.707.708zM3 10v.5a.5.5 0 0 0 .5.5H4v.5a.5.5 0 0 0 .5.5H5v.5a.5.5 0 0 0 .5.5H6v-1.5a.5.5 0 0 0-.5-.5H5v-.5a.5.5 0 0 0-.5-.5H3z"/>
|
|
125 |
</svg>
|
|
126 |
</button>
|
|
127 |
{/* End of Edit Button */}
|
|
128 |
</td>
|
|
129 |
</tr>
|
|
133 | 130 |
))} |
134 |
</tbody> |
|
135 |
</table> |
|
136 |
{/* Submit & Reject Button */} |
|
137 |
<div className="column"> |
|
138 |
{isEdit === true ? <button type="submit" className="btn btn-submit"> |
|
139 |
Save</button> : null} |
|
140 |
{isEdit === true ? ( |
|
141 |
<button onClick={cancel} type="submit" className="btn btn-cancel">Cancel</button> |
|
142 |
) : (null)} |
|
143 |
</div> |
|
144 |
</div> |
|
145 |
</form> |
|
131 |
</tbody> |
|
132 |
</table> |
|
133 |
{/* Submit & Reject Button */} |
|
134 |
<div className="column"> |
|
135 |
{isEdit === true ? ( |
|
136 |
<button type="submit" className="btn btn-submit">Save</button> |
|
137 |
) : ( |
|
138 |
<button onClick={cancel} type="submit" className="btn btn-cancel">Cancel</button> |
|
139 |
)} |
|
140 |
</div> |
|
141 |
</div> |
|
142 |
</form> |
|
143 |
</div> |
|
146 | 144 |
</div> |
147 |
</div> |
|
148 |
</div> |
|
149 |
); |
|
150 |
} |
|
151 |
|
|
152 |
|
|
153 |
export default OverviewAdmin; |
|
145 |
</div> |
|
146 |
); |
|
147 |
} |
client/src/Setting.js | ||
---|---|---|
1 | 1 |
import React, { useState, useEffect } from 'react'; |
2 | 2 |
import './App.css'; |
3 | 3 |
import { Link } from 'react-router-dom'; |
4 |
import * as api_fetch from './api'
|
|
4 |
import * as api from './api';
|
|
5 | 5 |
|
6 | 6 |
|
7 |
function Setting() { |
|
7 |
export default function Setting() {
|
|
8 | 8 |
|
9 |
const [sickdays, setSickdays] = useState(); |
|
10 |
|
|
11 |
useEffect( () => { |
|
12 |
api_fetch.getSettingData().then(settingData => { |
|
9 |
useEffect(() => { |
|
10 |
api.getSettingData().then(settingData => { |
|
13 | 11 |
setSetting(settingData); |
14 | 12 |
}).catch(reason => { |
15 |
alert(reason) |
|
16 |
}) |
|
13 |
alert(reason);
|
|
14 |
});
|
|
17 | 15 |
}, []); |
18 | 16 |
|
19 |
const submitSetting = async (e) => {
|
|
17 |
async function submitSetting(e) {
|
|
20 | 18 |
e.preventDefault(); |
21 |
|
|
19 |
|
|
22 | 20 |
const dataSettingObject = { |
23 |
"sickDayCount": Number(setting.sickday),
|
|
24 |
"notification": "2019/12/01 12:00:00"
|
|
25 |
} |
|
21 |
'sickDayCount': Number(setting.sickday),
|
|
22 |
'notification': '2019/12/01 12:00:00',
|
|
23 |
};
|
|
26 | 24 |
|
27 |
api_fetch.saveDataSetting(dataSettingObject).catch(reason => {
|
|
28 |
alert(reason) |
|
29 |
}) |
|
25 |
api.saveDataSetting(dataSettingObject).catch(reason => { |
|
26 |
alert(reason);
|
|
27 |
});
|
|
30 | 28 |
} |
29 |
|
|
31 | 30 |
// states |
32 |
const [setting, setSetting] = useState( |
|
33 |
{sickday: 5, |
|
34 |
holiday: 0 |
|
35 |
} |
|
36 |
) |
|
31 |
const [setting, setSetting] = useState({ |
|
32 |
sickday: 5, |
|
33 |
holiday: 0, |
|
34 |
}); |
|
37 | 35 |
|
38 | 36 |
//functions |
39 | 37 |
function changeSickday(newValue) { |
40 |
setSetting( |
|
41 |
{sickday: newValue,
|
|
42 |
holiday: 0
|
|
43 |
}) |
|
38 |
setSetting({
|
|
39 |
sickday: newValue, |
|
40 |
holiday: 0,
|
|
41 |
});
|
|
44 | 42 |
} |
45 | 43 |
|
46 | 44 |
return ( |
... | ... | |
60 | 58 |
</div> |
61 | 59 |
); |
62 | 60 |
} |
63 |
|
|
64 |
export default Setting; |
client/src/UpcomingRequests.js | ||
---|---|---|
1 |
import React, { useState, useEffect } from 'react';
|
|
1 |
import React, { useEffect } from 'react'; |
|
2 | 2 |
import './App.css'; |
3 | 3 |
import moment from 'moment'; |
4 |
import * as api_fetch from './api'
|
|
5 |
import convertVacationType from './convertVacationType' |
|
4 |
import * as api from './api';
|
|
5 |
import convertVacationType from './convertVacationType';
|
|
6 | 6 |
|
7 |
function UpcomingRequests(props) { |
|
7 |
export default function UpcomingRequests(props) {
|
|
8 | 8 |
|
9 |
useEffect( () => {
|
|
9 |
useEffect(() => { |
|
10 | 10 |
getData(); |
11 |
}, []); |
|
11 |
}, []); // eslint-disable-line
|
|
12 | 12 |
|
13 | 13 |
// get requests from server |
14 |
const getData = async () => { |
|
15 |
|
|
16 |
api_fetch.loadAdminRequests().then((data) => { |
|
14 |
async function getData() { |
|
15 |
api.loadAdminRequests().then((data) => { |
|
17 | 16 |
props.setUser(data.map(request => { |
17 |
const convertedStartDate = request.date.split('/').join('-'); |
|
18 | 18 |
|
19 |
const convertedStartDate = request.date.split("/").join("-"); |
|
20 |
|
|
21 |
return ( |
|
22 |
{ |
|
23 |
title: request.firstName + ' ' + request.lastName, |
|
24 |
id: request.id, |
|
25 |
type: convertVacationType(request.type), |
|
26 |
start: moment(convertedStartDate).format("D.M.YYYY"), |
|
27 |
end: null, |
|
28 |
status: request.status.toLowerCase() |
|
29 |
}) |
|
30 |
})) |
|
19 |
return ({ |
|
20 |
title: request.firstName + ' ' + request.lastName, |
|
21 |
id: request.id, |
|
22 |
type: convertVacationType(request.type), |
|
23 |
start: moment(convertedStartDate).format('D.M.YYYY'), |
|
24 |
end: null, |
|
25 |
status: request.status.toLowerCase(), |
|
26 |
}); |
|
27 |
})); |
|
31 | 28 |
}).catch(reason => { |
32 |
alert(reason) |
|
29 |
alert(reason);
|
|
33 | 30 |
}); |
34 |
} |
|
35 |
|
|
31 |
} |
|
36 | 32 |
|
37 | 33 |
// send accepted request to server |
38 |
const acceptRequest = async (user) => {
|
|
34 |
async function acceptRequest(user) {
|
|
39 | 35 |
try { |
40 |
|
|
41 | 36 |
const acceptedRequests = { |
42 | 37 |
id: user.id, |
43 | 38 |
status: 'ACCEPTED', |
44 |
} |
|
45 |
|
|
46 |
await api_fetch.sendAcceptedRequest(acceptedRequests).then(() => { |
|
47 |
|
|
39 |
}; |
|
40 |
|
|
41 |
await api.sendAcceptedRequest(acceptedRequests).then(() => { |
|
48 | 42 |
const userProps = { |
49 |
title: user.title,
|
|
50 |
type: user.type,
|
|
51 |
start: user.start
|
|
52 |
} |
|
43 |
title: user.title, |
|
44 |
type: user.type,
|
|
45 |
start: user.start,
|
|
46 |
};
|
|
53 | 47 |
//concat new request to current ones |
54 |
props.setAcceptedRequest((acceptedRequest) => acceptedRequest.concat(userProps))
|
|
48 |
props.setAcceptedRequest((acceptedRequest) => acceptedRequest.concat(userProps));
|
|
55 | 49 |
//request accept button |
56 |
props.setUser((pendingRequest) => pendingRequest.filter((item) => item !== user));
|
|
57 |
}) |
|
50 |
props.setUser((pendingRequest) => pendingRequest.filter((item) => item !== user)); |
|
51 |
});
|
|
58 | 52 |
} catch (e) { |
59 |
alert(e) |
|
53 |
alert(e);
|
|
60 | 54 |
} |
61 | 55 |
} |
62 | 56 |
|
63 |
|
|
64 | 57 |
//send rejected request to server |
65 |
const declineRequest = async (user) => { |
|
66 |
try{ |
|
67 |
|
|
58 |
async function declineRequest(user) { |
|
59 |
try { |
|
68 | 60 |
const rejectedRequest = { |
69 | 61 |
id: user.id, |
70 | 62 |
status: 'REJECTED', |
71 |
} |
|
63 |
}; |
|
64 |
|
|
65 |
await api.sendRejectedRequest(rejectedRequest); |
|
72 | 66 |
|
73 |
await api_fetch.sendRejectedRequest(rejectedRequest); |
|
74 |
|
|
75 |
props.setUser((acceptedRequest) => acceptedRequest.filter((item) => item !== user)) |
|
67 |
props.setUser((acceptedRequest) => acceptedRequest.filter((item) => item !== user)); |
|
76 | 68 |
|
77 |
const usersOverview = await api_fetch.getUsersOverview();
|
|
69 |
const usersOverview = await api.getUsersOverview(); |
|
78 | 70 |
props.setEmployees(usersOverview); |
79 | 71 |
|
80 |
} catch (e) { |
|
81 |
alert(e)
|
|
72 |
} catch (e) {
|
|
73 |
alert(e);
|
|
82 | 74 |
} |
83 | 75 |
} |
84 | 76 |
|
... | ... | |
89 | 81 |
<div className="offs-items column"> |
90 | 82 |
<div className="offs-item row"> |
91 | 83 |
<table> |
92 |
{props.user.length > 0 ? |
|
93 |
<tbody> |
|
94 |
<tr> |
|
95 |
<th>Name</th> |
|
96 |
<th>Type</th> |
|
97 |
<th>Date</th> |
|
98 |
</tr> |
|
99 |
{props.user.map(user => ( |
|
100 |
<tr> |
|
101 |
<td>{user.title}</td> |
|
102 |
<td>{user.type}</td> |
|
103 |
<td>{user.end ? user.start + " - " + user.end : user.start}</td> |
|
104 |
<div className="offs-btn row"> |
|
105 |
<button onClick={() => acceptRequest(user)} type="submit" className="btn btn-submit">Accept</button> |
|
106 |
<button onClick={() => declineRequest(user)} type="submit" className="btn btn-cancel">Decline</button> |
|
107 |
</div> |
|
108 |
</tr> |
|
109 |
))} |
|
110 |
</tbody> |
|
111 |
: |
|
112 |
<tbody> |
|
113 |
<p>There are no requests.</p> |
|
114 |
</tbody>} |
|
115 |
</table> |
|
84 |
{props.user.length > 0 ? ( |
|
85 |
<tbody> |
|
86 |
<tr> |
|
87 |
<th>Name</th> |
|
88 |
<th>Type</th> |
|
89 |
<th>Date</th> |
|
90 |
</tr> |
|
91 |
{props.user.map(user => ( |
|
92 |
<tr key={user.id}> |
|
93 |
<td>{user.title}</td> |
|
94 |
<td>{user.type}</td> |
|
95 |
<td>{user.end ? user.start + ' - ' + user.end : user.start}</td> |
|
96 |
<div className="offs-btn row"> |
|
97 |
<button onClick={() => acceptRequest(user)} type="submit" className="btn btn-submit">Accept</button> |
|
98 |
<button onClick={() => declineRequest(user)} type="submit" className="btn btn-cancel">Decline</button> |
|
99 |
</div> |
|
100 |
</tr> |
|
101 |
))} |
|
102 |
</tbody> |
|
103 |
) : ( |
|
104 |
<tbody> |
|
105 |
<p>There are no requests.</p> |
|
106 |
</tbody> |
|
107 |
)} |
|
108 |
</table> |
|
116 | 109 |
</div> |
117 | 110 |
</div> |
118 | 111 |
</div> |
119 |
) |
|
120 |
} |
|
121 |
|
|
122 |
export default UpcomingRequests; |
|
112 |
); |
|
113 |
} |
client/src/YourRequests.js | ||
---|---|---|
1 | 1 |
import React, { useEffect } from 'react'; |
2 | 2 |
import './App.css'; |
3 | 3 |
import moment from 'moment'; |
4 |
import * as api_fetch from './api'
|
|
5 |
import convertVacationType from './convertVacationType' |
|
4 |
import * as api from './api';
|
|
5 |
import convertVacationType from './convertVacationType';
|
|
6 | 6 |
|
7 |
function YourRequests(props) { |
|
7 |
export default function YourRequests(props) {
|
|
8 | 8 |
|
9 | 9 |
useEffect( () => { |
10 |
if (props.currentUser !== undefined) {
|
|
11 |
getData();
|
|
10 |
if (props.currentUser === undefined) {
|
|
11 |
return;
|
|
12 | 12 |
} |
13 |
}, [props.currentUser]); |
|
14 | 13 |
|
15 |
// get requests from server |
|
16 |
const getData = async () => { |
|
17 |
|
|
18 |
api_fetch.loadYourRequests(props.currentUser).then((data) => { |
|
14 |
getData(); |
|
15 |
}, [props.currentUser]); // eslint-disable-line |
|
19 | 16 |
|
17 |
// get requests from server |
|
18 |
async function getData() { |
|
19 |
api.loadYourRequests(props.currentUser).then((data) => { |
|
20 | 20 |
props.setUser(data.map(request => { |
21 |
const convertedDate = request.date.split("/").join("-");
|
|
21 |
const convertedDate = request.date.split('/').join('-');
|
|
22 | 22 |
|
23 |
return ( |
|
24 |
{ |
|
23 |
return ({ |
|
25 | 24 |
title: props.currentUser.name, |
26 | 25 |
id: request.id, |
27 |
start: moment(convertedDate).format("D.M.YYYY"), |
|
28 |
status: request.status = request.status.toLowerCase(), |
|
29 |
type: convertVacationType(request.type) |
|
30 |
} |
|
31 |
) |
|
32 |
})) |
|
26 |
start: moment(convertedDate).format('D.M.YYYY'), |
|
27 |
status: request.status.toLowerCase(), |
|
28 |
type: convertVacationType(request.type), |
|
29 |
}); |
|
30 |
})); |
|
33 | 31 |
}).catch(reason => { |
34 |
alert(reason) |
|
32 |
alert(reason);
|
|
35 | 33 |
}); |
36 |
} |
|
34 |
}
|
|
37 | 35 |
|
38 | 36 |
return ( |
39 | 37 |
<div className="offs-request column"> |
... | ... | |
42 | 40 |
<div className="offs-items column"> |
43 | 41 |
<div className="offs-item row"> |
44 | 42 |
<table> |
45 |
{props.user.length > 0 ? |
|
46 |
|
|
47 |
<tbody>
|
|
48 |
<tr>
|
|
49 |
<th>Name</th>
|
|
50 |
<th>Type</th>
|
|
51 |
<th>Date</th>
|
|
52 |
<th>Status</th>
|
|
53 |
</tr>
|
|
54 |
{props.user.map(user => (
|
|
55 |
<tr key={user.id}>
|
|
56 |
<td>{user.title}</td>
|
|
57 |
<td>{user.type}</td>
|
|
58 |
<td>{user.end ? user.start + " - " + user.end : user.start}</td>
|
|
59 |
<td>{user.status}</td>
|
|
60 |
</tr>
|
|
61 |
))}
|
|
62 |
</tbody>
|
|
63 |
:
|
|
64 |
<tbody>
|
|
65 |
<div>No requests</div>
|
|
66 |
</tbody>}
|
|
43 |
{props.user.length > 0 ? (
|
|
44 |
<tbody> |
|
45 |
<tr>
|
|
46 |
<th>Name</th>
|
|
47 |
<th>Type</th>
|
|
48 |
<th>Date</th>
|
|
49 |
<th>Status</th>
|
|
50 |
</tr>
|
|
51 |
{props.user.map(user => (
|
|
52 |
<tr key={user.id}>
|
|
53 |
<td>{user.title}</td>
|
|
54 |
<td>{user.type}</td>
|
|
55 |
<td>{user.end ? user.start + ' - ' + user.end : user.start}</td>
|
|
56 |
<td>{user.status}</td>
|
|
57 |
</tr>
|
|
58 |
))}
|
|
59 |
</tbody>
|
|
60 |
) : (
|
|
61 |
<tbody>
|
|
62 |
<div>No requests</div>
|
|
63 |
</tbody>
|
|
64 |
)}
|
|
67 | 65 |
</table> |
68 | 66 |
</div> |
69 | 67 |
</div> |
70 | 68 |
</div> |
71 |
) |
|
69 |
);
|
|
72 | 70 |
} |
73 |
|
|
74 |
|
|
75 |
export default YourRequests; |
client/src/api.js | ||
---|---|---|
1 |
// ******************** Log Out ******************** |
|
2 |
|
|
3 |
export const logOut = async () => { |
|
1 |
import * as HttpStatus from './HttpStatus'; |
|
4 | 2 |
|
3 |
/** |
|
4 |
* Log Out |
|
5 |
*/ |
|
6 |
export async function logOut() { |
|
5 | 7 |
let response; |
6 | 8 |
|
7 | 9 |
try { |
8 |
response = await fetch( |
|
9 |
`${window.config.baseUrl}/logout`, { |
|
10 |
credentials: 'include' |
|
11 |
} |
|
12 |
); |
|
10 |
response = await fetch(`${window.config.baseUrl}/logout`, { |
|
11 |
credentials: 'include', |
|
12 |
}); |
|
13 | 13 |
} catch (e) { |
14 |
throw 'Server is not available'
|
|
15 |
}
|
|
14 |
throw new Error('Server is not available');
|
|
15 |
} |
|
16 | 16 |
|
17 | 17 |
if (response.ok) { |
18 |
window.location.replace(`/logout`)
|
|
18 |
window.location.replace('/logout');
|
|
19 | 19 |
} else { |
20 |
switch (response.status) { |
|
21 |
case 500: |
|
22 |
throw new Error('Internal server error.') |
|
23 |
default: |
|
24 |
throw new Error(response.statusText) |
|
25 |
} |
|
20 |
switch (response.status) { |
|
21 |
case HttpStatus.INTERNAL_SERVER_ERROR: |
|
22 |
throw new Error('Internal server error.'); |
|
23 |
default: |
|
24 |
throw new Error(response.statusText); |
|
26 | 25 |
} |
26 |
} |
|
27 | 27 |
} |
28 | 28 |
|
29 |
// ******************** GET DATA APP getCurrentProfile ********************
|
|
30 |
|
|
31 |
export const getCurrentProfile = async () => {
|
|
32 |
|
|
29 |
/** |
|
30 |
* GET DATA APP getCurrentProfile |
|
31 |
*/
|
|
32 |
export async function getCurrentProfile() { |
|
33 | 33 |
let response; |
34 | 34 |
|
35 | 35 |
try { |
36 |
response = await fetch( |
|
37 |
`${window.config.baseUrl}/users/current/profile`, { |
|
38 |
|
|
39 |
credentials: 'include' |
|
40 |
} |
|
41 |
); |
|
36 |
response = await fetch(`${window.config.baseUrl}/users/current/profile`, { |
|
37 |
credentials: 'include', |
|
38 |
}); |
|
42 | 39 |
} catch (e) { |
43 |
throw 'Server is not available'
|
|
44 |
}
|
|
40 |
throw new Error('Server is not available');
|
|
41 |
} |
|
45 | 42 |
|
46 | 43 |
if (response.ok) { |
47 | 44 |
const data = await response.json(); |
... | ... | |
53 | 50 |
holiday: data.vacationCount, |
54 | 51 |
sickday: data.sickDayCount, |
55 | 52 |
photo: data.photo, |
56 |
takenSickday: data.takenSickDayCount |
|
57 |
} |
Také k dispozici: Unified diff
re #58 massive code formatting