Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- #31

Merged
merged 43 commits into from
Apr 3, 2024
Merged

- #31

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
606e77b
redesigning the line manager search
Apr 1, 2024
5809843
Merge branch 'main' into luke_front_end_new
Apr 1, 2024
937a8ae
fetch data from endpoint for timesheet viewing
Apr 2, 2024
cf163ed
view timesheet page now displays data for days in the table
Apr 2, 2024
3ae8668
Finished create timesheet page
krish2903 Apr 2, 2024
34f9f1a
started on weekly approvals, added consultant and line manager names …
delterr Apr 2, 2024
34aeb20
fix typo
delterr Apr 2, 2024
6b58afe
line manager consultant search page changes
Apr 2, 2024
b9f8f44
Merge branch 'main' into luke_front_end_new
Apr 2, 2024
7b4835a
nother bug fix lol
delterr Apr 2, 2024
b020383
Merge branch 'main' into luke_front_end_new
Apr 2, 2024
8851854
view timesheet page now displays all info (excluding hourly rate)
Apr 2, 2024
a50c035
Finance team page
Apr 3, 2024
7c2e573
financeteampage
Apr 3, 2024
7d69226
Merge branch 'main' into luke_front_end_new
Apr 3, 2024
3b5b749
fix
Apr 3, 2024
3fdd53b
Merge pull request #21 from NotMash/luke_front_end_new
Nameless7s3 Apr 3, 2024
5e1efb4
Merge pull request #20 from NotMash/krish_backend
Nameless7s3 Apr 3, 2024
dc27d3d
made a responsive nav bar for user pages
Apr 3, 2024
49e475c
added nav bar to every single page
Apr 3, 2024
dd42711
Merge branch 'main' into luke_front_end_new
Nameless7s3 Apr 3, 2024
a19b76c
Merge pull request #22 from NotMash/luke_front_end_new
Nameless7s3 Apr 3, 2024
56532c6
merged krish's changes with mine and fixed some stuff
Apr 3, 2024
e3ce074
Merge branch 'luke_front_end_new' of https://github.com/NotMash/SWE-T…
Apr 3, 2024
1a4affc
Merge pull request #23 from NotMash/luke_front_end_new
Nameless7s3 Apr 3, 2024
e121e1f
bug fixes with line manager page
Apr 3, 2024
2eaaf17
added endpoint for listing consultants
delterr Apr 3, 2024
3c06062
Merge branch 'main' of https://github.com/NotMash/SWE-TIMESHEET into …
delterr Apr 3, 2024
f53a357
Merge pull request #24 from NotMash/main
krish2903 Apr 3, 2024
9011ce8
update update
delterr Apr 3, 2024
366f468
cleaned up line manager search page and added login button to navbar
Apr 3, 2024
068447f
Merge pull request #25 from NotMash/ibrahim_finalV1
NotMash Apr 3, 2024
9398115
Merge pull request #26 from NotMash/ibrahim_finalV1
NotMash Apr 3, 2024
eae6c3f
connecting line manager search to backend
Apr 3, 2024
d2ed3b5
Set Hourly Page and User Creation Update
krish2903 Apr 3, 2024
3b0ceed
Merge branch 'main' into krish_backend
krish2903 Apr 3, 2024
6514c84
Merge pull request #27 from NotMash/krish_backend
Nameless7s3 Apr 3, 2024
4b05754
Merge branch 'main' into luke_front_end_new
Apr 3, 2024
90cdfbd
fixed bug with consultant not being able to be created
Apr 3, 2024
6f2084e
Merge pull request #29 from NotMash/luke_front_end_new
Nameless7s3 Apr 3, 2024
446768f
logout button positioning fixes
Apr 3, 2024
3b0484e
some design fixes
Apr 3, 2024
2be9780
Merge pull request #30 from NotMash/luke_front_end_new
Nameless7s3 Apr 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified backend/flask_session/2029240f6d1128be89ddc32729463129
Binary file not shown.
Binary file modified backend/flask_session/679eaac484e8efec851e5d02a21b12ac
Binary file not shown.
Binary file not shown.
Binary file modified backend/flask_session/d809bf2dcbe2110e634be9cd9bce2102
Binary file not shown.
54 changes: 44 additions & 10 deletions backend/timesheets/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ class HomeView(MethodView):
def get(self):
return "Done", 200

class ListConsultantsView(MethodView):
def get(self):
user_id = session.get("user_id")
line_manager = LineManager.query.filter_by(id=user_id)

if line_manager != None:
consultants = Consultant.query.filter_by(line_manager_id=user_id)
else:
return jsonify({"Error": "Unauthorized"}), 400

json_dict = {}
for consultant in consultants:
json_dict[consultant.username] = {"username": consultant.username, "consultant_id": consultant.id}

return jsonify(json_dict), 200


class CurrentUserView(MethodView):
def get(self):
Expand Down Expand Up @@ -139,13 +155,14 @@ def get(self):
json_dict = {}
timesheet_ids = [timesheet.id for timesheet in timesheets]
for timesheet in timesheets:
json_dict[timesheet.id] = {"name": timesheet.consultant_name, "status": timesheet.status}
json_dict[timesheet.id] = {"id": timesheet.id, "name": timesheet.consultant_name, "status": timesheet.status}
return jsonify(json_dict), 200

class ListWeeklyTimesheetsView(MethodView):
def get(self):
user_id = session.get("user_id")
consultant = Consultant.query.filter_by(id=user_id).first()
# line_manager = LineManager.query.filter_by(username=consultant.line_manager.username).first()
print(consultant)

if consultant == None:
Expand All @@ -160,18 +177,34 @@ def get(self):
for timesheet in timesheets:
hours_worked = str(timedelta(seconds=timesheet.hours_worked))
day = f"{timesheet.day.day}/{timesheet.day.month}/{timesheet.day.year}"
json_dict[timesheet.id] = {"start_work": timesheet.start_work_time, "end_work": timesheet.end_work_time, "week_start": week_start, "hours_worked": hours_worked, "day": day}
json_dict[timesheet.id] = {"start_work": timesheet.start_work_time, "end_work": timesheet.end_work_time,
"week_start": week_start, "hours_worked": hours_worked, "day": day,
"consultant_name": f"{consultant.firstname} {consultant.lastname}",
"line_manager_name": f"{consultant.line_manager.firstname} {consultant.line_manager.lastname}"}
return jsonify(json_dict), 200


class ListConsultantsView(MethodView):
def get(self):
class WeeklyTimesheetsApprovalView(MethodView):
def post(self, consultant_username, flag):
user_id = session.get("user_id")
consultants = Consultant.query.filter_by(line_manager_id=user_id)
json_dict = {}
for consultant in consultants:
json_dict[consultant.id] = consultant.username
return jsonify(json_dict), 200
line_manager = LineManager.query.filter_by(id=user_id)
consultant = Consultant.query.filter_by(username=consultant_username)

week_start = datetime.today() - timedelta(days=datetime.today().weekday() % 7)
week_start = datetime(week_start.year, week_start.month, week_start.day)
week_start = f"{week_start.day}/{week_start.month}/{week_start.year}"
timesheets = Timesheet.query.filter_by(week_start_date=week_start, username=consultant_username).all()

for timesheet in timesheets :
if flag == "approve":
timesheet.status = "approved"
db.session.commit()
elif flag == "disapprove":
timesheet.status = "disapproved"
else:
return jsonify({"Error": "Invalid flag"}), 400

return jsonify("Success"), 200

class ListConsultantTimesheetsView(MethodView):
def get(self, consultant_id):
Expand Down Expand Up @@ -369,7 +402,8 @@ def post(self, consultant_username,):
app.add_url_rule("/delete_timesheet/<timesheet_id>", view_func=timesheets_view, methods=["DELETE"])
app.add_url_rule("/list_timesheets", view_func=ListTimesheetsView.as_view("list_timesheets_view"), methods=["GET"])
app.add_url_rule("/list_weekly_timesheets", view_func=ListWeeklyTimesheetsView.as_view("list_weekly_timesheets_view"), methods=["GET"])
app.add_url_rule("/list_timesheets/<consultant_id>", view_func=ListConsultantTimesheetsView.as_view("list_consultant_timesheets_view"), methods=["GET"])
app.add_url_rule("/list_weekly_timesheets/<consultant_username>/<flag>", view_func=WeeklyTimesheetsApprovalView.as_view("list_weekly_timesheets_approval"), methods=["POST"])
app.add_url_rule("/list_timesheets/<consultant_id>", view_func=ListConsultantTimesheetsView.as_view("list_consultant_timesheets_viewpost"), methods=["GET"])
app.add_url_rule("/approve_timesheet/<timesheet_id>", view_func=TimesheetApprovalView.as_view("timesheet_approval_view"), methods=["POST"])
app.add_url_rule("/disapprove_timesheet/<timesheet_id>", view_func=TimesheetDisapprovalView.as_view("timesheet_disapproval_view"), methods=["POST"])

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/Home_Page_Icons/house-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/Home_Page_Icons/logout.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 6 additions & 3 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
rel="stylesheet"
/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Expand Down
43 changes: 38 additions & 5 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { HashRouter, Routes, Route} from "react-router-dom";
import { HashRouter, Routes, Route } from "react-router-dom";
import MainHome from "./Pages/Main/main_home";
import LoginPage from "./Pages/Main/login_page";
import ConsultantHomePage from "./Pages/Consultant/consultant_home_page";
import FinanceTeamMemberHomePage from "./Pages/Finance_Team/finance_team_mem_home_page";
import SetHourlyRate from "./Components/Finance_Team_Page/SetHourlyRate";
import ViewTimesheet from "./Components/Finance_Team_Page/ViewTimesheet";
import ITTechnicianHomePage from "./Pages/IT_Technician/it_technician_home_page";
import LineManagerHomePage from "./Pages/Line_Manager/line_manager_home_page";
import TimesheetRecordingPage from "./Pages/Consultant/timesheet_recording_page";
Expand All @@ -12,11 +14,42 @@ import TimesheetEditRequestsPage from "./Pages/IT_Technician/timesheet_edit_requ
import ItUserCreationPage from "./Pages/IT_Technician/it_user_creation_page";
import ViewCurrentTimesheetPage from "./Pages/Consultant/view_current_timesheet_page";

function App()
{
return(
function App() {
return (
<HashRouter>
<Routes>
<Route path="/" element={<MainHome />} />
<Route path="/login_page" element={<LoginPage />} />
<Route path="/consultant_home_page" element={<ConsultantHomePage />} />
<Route
path="/finance_team_member_home_page"
element={<FinanceTeamMemberHomePage />}
/>
<Route path="/set_hourly_rate" element={<SetHourlyRate />} />
<Route path="/view_timesheet" element={<ViewTimesheet />} />

<Route
path="/it_technician_home_page"
element={<ITTechnicianHomePage />}
/>
<Route
path="/line_manager_home_page"
element={<LineManagerHomePage />}
/>
<Route
path="/timesheet_recording_page"
element={<TimesheetRecordingPage />}
/>
<Route
path="/consultant_finder_page"
element={<ConsultantFinderPage />}
/>
<Route path="/it_difficulties" element={<ItDifficultiesPage />} />
<Route
path="/timesheet_edit_requests"
element={<TimesheetEditRequestsPage />}
/>
<Route path="/it_user_creation" element={<ItUserCreationPage />} />
<Route path="/" element={<MainHome/>}/>
<Route path="/login_page" element={<LoginPage/>}/>
<Route path="/consultant_home_page" element={<ConsultantHomePage/>}/>
Expand All @@ -31,7 +64,7 @@ function App()
<Route path="/current_timesheet_viewer" element={<ViewCurrentTimesheetPage/>}/>
</Routes>
</HashRouter>
)
);
}

export default App;
63 changes: 63 additions & 0 deletions frontend/src/Components/Finance_Team_Page/SetHourlyRate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useState } from "react";
import styles from "./SetHourlyRate.module.css"; // Import the CSS file
import Navbar from "../../Components/Global/Navbar";

function SetHourlyRate() {
let links = [{ pageName: "Set Hourly Rate Page", pageLink: "/set_hourly_rate", iconPath: "./Home_Page_Icons/Consultant/record_timesheet.svg" },
{ pageName: "View Timesheet Page", pageLink: "/view_timesheet", iconPath: "./Home_Page_Icons/Consultant/view_timesheet.svg" }]

const [consultantName, setConsultantName] = useState("");
const [hourlyRate, setHourlyRate] = useState("");

const handleConsultantNameChange = (event) => {
setConsultantName(event.target.value);
};

const handleHourlyRateChange = (event) => {
setHourlyRate(event.target.value);
};

const handleSubmit = (event) => {
event.preventDefault();
// Here, you can send the data to the backend
// For now, let's just log the data to the console
console.log("Consultant Name:", consultantName);
console.log("Hourly Rate:", hourlyRate);
};

return (
<>
<Navbar homePageTitle="Finance Team Home Page" homePageLink="/finance_team_member_home_page" links={links} />
<div className={styles.setHourlyRateContainer}>
<h2 className={styles.setHourlyRateTitle}>Set Hourly Rate</h2>
<form className={styles.formContainer} onSubmit={handleSubmit}>
<div className={styles.inputGroup}>
<p className={styles.setHourlyRateLabel}>Consultant Name:</p>
<input
type="text"
value={consultantName}
onChange={handleConsultantNameChange}
className={styles.setHourlyRateInput}
placeholder="Enter consultant's name"
/>
</div>
<div className={styles.inputGroup}>
<p className={styles.setHourlyRateLabel}>Hourly Rate:</p>
<input
type="number"
value={hourlyRate}
onChange={handleHourlyRateChange}
className={styles.setHourlyRateInput}
placeholder="Enter hourly rate"
/>
</div>
<button type="submit" className={styles.setHourlyRateButton}>
Set Hourly Rate
</button>
</form>
</div>
</>
);
}

export default SetHourlyRate;
104 changes: 104 additions & 0 deletions frontend/src/Components/Finance_Team_Page/SetHourlyRate.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* SetHourlyRate.module.css */

/* Container styles */
.setHourlyRateContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
height: 100%; /* Set the container height to viewport height */
padding: 20px; /* Add padding */
margin-left: 5rem;
font-family: "Roboto", sans-serif;
}

/* Title styles */
.setHourlyRateTitle {
letter-spacing: 3px;
text-align: center;
font-size: 30pt;
margin-bottom: 50px; /* Add margin at the bottom */
font-weight: bolder;
}

/* Label styles */
.setHourlyRateLabel {
font-size: 18px; /* Increase font size */
color: white; /* Change text color */
}

.inputGroup {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.setHourlyRateInput {
font-weight: 500;
font-size: 11pt;
color: #fff;
background-color: rgb(28,28,30);
box-shadow: 0 0 .4vw rgba(0,0,0,0.5), 0 0 0 .15vw transparent;
border-radius: 15px;
border: none;
outline: none;
padding: 0.4vw;
max-width: 100%;
height: 25px;
transition: .4s;
text-align: center;
}

.setHourlyRateInput::placeholder {
color: rgba(255, 255, 255, 0.382);
}

.setHourlyRateInput:hover {
box-shadow: 0 0 0 .15vw #c5ff00;
}

.setHourlyRateInput:focus {
box-shadow: 0 0 0 .15vw #c5ff00;
}

.formContainer {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.setHourlyRateButton {
font-family: "Poppins", sans-serif;
width: 15%;
padding: 1%;
margin: 3%;
border-radius: 50px;
cursor: pointer;
border: 0;
background-color: white;
box-shadow: rgb(0 0 0 / 5%) 0 0 8px;
letter-spacing: 1.5px;
text-transform: uppercase;
font-size: 15px;
transition: all 0.5s ease;
}

.setHourlyRateButton:hover {
letter-spacing: 2px;
background-color: #1e1e1e;
color: hsl(0, 0%, 100%);
box-shadow: #c5ff00 0px 3px 29px 0px;
}

.setHourlyRateButton:active {
letter-spacing: 2px;
background-color: #1e1e1e;
color: white;
box-shadow: #c5ff00 0px 0px 0px 0px;
transform: translateY(10px);
transition: 100ms;
}
Loading