-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
83 changed files
with
3,428 additions
and
1,515 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"editor.formatOnSave": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,33 @@ | ||
## Nurse scheduling problem | ||
# Nurse Scheduling Problem | ||
|
||
The algorithm implementation is a part of solution created for [Fundacja Rodzin Adopcyjnych](https://adopcja.org.pl), the adoption foundation in Warsaw (Poland) during Project Summer [AILab](http://www.ailab.agh.edu.pl) & [Glider](http://www.glider.agh.edu.pl) 2020 event. The aim of the system is to improve the operation of the foundation by easily and quickly creating work schedules for its employees and volunteers. So far, this has been done manually in spreadsheets, which is a cumbersome and tedious job. | ||
|
||
The solution presented here is problem-specific. It assumes a specific form of input and output schedules, which was adopted in the foundation for which the system is created. The schedules themselves are adjusted based on the rules of the Polish Labour Code. | ||
|
||
The system consists of three components which are on two GitHub repositories: | ||
|
||
- web application which allows the user to load a schedule, modify it, set basic requirements, have it sent to solver service to be adjusted for another month and display discrepancies between shifts as seen in schedule and the rules of the Polish Labour Code | ||
- solver written in Julia which adjusts schedules and provides information about points where the schedules do not adhere to the Polish Labour Code, if they arise (detailed information [here](https://github.com/Project-Summer-AI-Lab-Glider/nurse-scheduling-problem-solver)) | ||
- backend also written in Julia ([Genie framework](https://genieframework.com/)) which allows for communication of both aforementioned components (detailed information [here](https://github.com/Project-Summer-AI-Lab-Glider/nurse-scheduling-problem-solver)) | ||
|
||
This repository contains the frontend web application, and also a mock backend server created for testing purposes. | ||
|
||
## Running an app | ||
|
||
``` | ||
git clone https://github.com/Project-Summer-AI-Lab-Glider/nurse-scheduling-problem-frontend.git nurse-scheduling | ||
cd nurse-scheduling/frontend | ||
npm install | ||
npm start | ||
``` | ||
## Running Mock Backend Server | ||
Have python, pip and venv installed, cd into backend/server, then | ||
|
||
``` | ||
python3 -m venv venv | ||
source venv/bin/activate | ||
pip install -r requirements.txt | ||
source venv/bin/activate | ||
export FLASK_APP=example_server.py | ||
python -m flask run | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import React from "react"; | ||
|
||
function LegendComponent () { | ||
// in future here will be added some more logic: | ||
// for example editing of colors for shifts | ||
return <React.Fragment></React.Fragment> | ||
function LegendComponent() { | ||
// in future here will be added some more logic: | ||
// for example editing of colors for shifts | ||
return <React.Fragment></React.Fragment>; | ||
} | ||
export default LegendComponent; | ||
export default LegendComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
.add-worker-button { | ||
left: 50%; | ||
transform: translate(-50%); | ||
width: 50%; | ||
} | ||
|
||
.worker-modal { | ||
position: absolute; | ||
width: 400px; | ||
background-color: white; | ||
border: 2px solid #000; | ||
padding: 20px; | ||
left: 50%; | ||
margin-left: -200px; | ||
top: 50%; | ||
margin-top: -200px; | ||
} |
146 changes: 146 additions & 0 deletions
146
frontend/src/components/table/modal/add-worker-modal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import React, { useEffect, useState } from "react"; | ||
import { Modal, TextField } from "@material-ui/core"; | ||
import "./add-worker-modal.css"; | ||
import { | ||
WorkerType, | ||
WorkerTypeHelper, | ||
} from "../../../state/models/schedule-data/employee-info.model"; | ||
import Button from "@material-ui/core/Button"; | ||
|
||
const initialState = { | ||
name: "", | ||
nameError: false, | ||
time: "", | ||
timeError: false, | ||
actionName: "Dodaj nowego pracownika do sekcji", | ||
isNewWorker: false, | ||
}; | ||
|
||
export interface WorkerInfo { | ||
name?: string; | ||
time?: number; | ||
} | ||
|
||
interface AddWorkerModalOptions { | ||
isOpened: boolean; | ||
setIsOpened: (status: boolean) => void; | ||
submit: (workerInfo: WorkerInfo) => void; | ||
workerType: WorkerType; | ||
workerInfo?: WorkerInfo; | ||
} | ||
const NAME_MIN_LENGTH = 5; | ||
|
||
export function AddWorkerModal({ | ||
isOpened, | ||
setIsOpened, | ||
submit, | ||
workerType, | ||
workerInfo, | ||
}: AddWorkerModalOptions) { | ||
const [{ name, nameError, time, timeError, actionName, isNewWorker }, setState] = useState( | ||
initialState | ||
); | ||
|
||
useEffect(() => { | ||
const { name = "", time = 0 } = workerInfo || {}; | ||
const isNewWorker = name.length === 0; | ||
const actionName = isNewWorker | ||
? `Dodaj nowego pracownika do sekcji ${WorkerTypeHelper.translate(workerType, true)}` | ||
: `Edytuj pracownika: ${name}`; | ||
setState((prev) => ({ | ||
...prev, | ||
name, | ||
time: time + "", | ||
actionName, | ||
isNewWorker, | ||
})); | ||
}, [workerInfo, workerType]); | ||
|
||
const clearState = () => { | ||
setState({ ...initialState }); | ||
}; | ||
|
||
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const { name: controlName, value } = e.target; | ||
setState((prevState) => ({ ...prevState, [controlName]: value })); | ||
}; | ||
|
||
const parseTimeIfPossible = (time) => { | ||
if (new RegExp("([0].[0-9])|(1.0)|(1)").test(time)) { | ||
return { isTimeFormatValid: true, parsedTime: Number(time) }; | ||
} | ||
if (new RegExp("[1-9]/[0-9]").test(time)) { | ||
const timerArray = time.split("/"); | ||
if (timerArray[0] <= timerArray[1]) { | ||
return { isTimeFormatValid: true, parsedTime: Number(timerArray[0] / timerArray[1]) }; | ||
} | ||
} | ||
return { isTimeFormatValid: false }; | ||
}; | ||
|
||
const validateName = (name) => { | ||
return name.length >= NAME_MIN_LENGTH; | ||
}; | ||
|
||
const handleSubmit = () => { | ||
const { isTimeFormatValid, parsedTime } = parseTimeIfPossible(time); | ||
const isNameValid = validateName(name); | ||
|
||
if (isTimeFormatValid) { | ||
setState((prevState) => ({ ...prevState, timeError: false })); | ||
if (isNameValid) { | ||
submit({ name, time: parsedTime }); | ||
handleClose(); | ||
} else { | ||
setState((prevState) => ({ ...prevState, nameError: true })); | ||
} | ||
} else { | ||
setState((prevState) => ({ ...prevState, timeError: true })); | ||
} | ||
}; | ||
|
||
const handleClose = () => { | ||
clearState(); | ||
setIsOpened(false); | ||
}; | ||
|
||
const body = ( | ||
<div className="worker-modal"> | ||
<h2 id="modal-title">{actionName}</h2> | ||
<form> | ||
<TextField | ||
id="name-input" | ||
label="Imię i nazwisko" | ||
value={name} | ||
name="name" | ||
inputProps={{ | ||
readOnly: !isNewWorker, | ||
}} | ||
onChange={onChange} | ||
required | ||
error={nameError} | ||
helperText={`Musi mieć co najmniej ${NAME_MIN_LENGTH} znaków`} | ||
/> | ||
<TextField | ||
id="time-input" | ||
label="Etat" | ||
value={time} | ||
name={"time"} | ||
onChange={onChange} | ||
required | ||
helperText={"Obsługiwane formaty to: dziesiętny np. 0.1 i ułamkowy np. 3/5"} | ||
error={timeError} | ||
/> | ||
<Button onClick={handleSubmit} className="add-worker-button" variant="outlined"> | ||
Dodaj | ||
</Button> | ||
</form> | ||
</div> | ||
); | ||
|
||
return ( | ||
<Modal open={isOpened} onClose={handleClose}> | ||
{body} | ||
</Modal> | ||
); | ||
} |
Oops, something went wrong.