diff --git a/client/public/global.css b/client/public/global.css
index dd6ecee4c..9af1a8e7d 100644
--- a/client/public/global.css
+++ b/client/public/global.css
@@ -360,18 +360,17 @@ h1, h2, h3, h4, h5, h6 {
color: white;
margin-top: 20px !important;
}
-.event__birthday{
+.event__birthday {
text-align: center;
color: white;
- margin-top: -95px !important;
- width: 30px;
+ margin-top: -100px !important;
+ width: 35px;
border-radius: 50%;
- height: 30px;
+ height: 35px;
display: flex;
align-items: center;
justify-content: center;
- margin-left: 125px;
- /* padding: 20px; */
+ margin-left: 115px;
}
.p-relative{
position: relative;
diff --git a/client/src/apis/home/home.ts b/client/src/apis/home/home.ts
index 6367f0c93..34992d2e1 100644
--- a/client/src/apis/home/home.ts
+++ b/client/src/apis/home/home.ts
@@ -25,17 +25,19 @@ class HomePage {
location: string;
}) {
try {
+ console.log("e: ", e);
+
if (
!e.name ||
- !e.people ||
- e.people.length === 0 ||
+ // !e.people ||
+ // e.people.length === 0 ||
!e.end_date ||
- !e.location ||
+ // !e.location ||
!e.end_time ||
!e.from_time
)
throw new Error("Invalid data");
- if (e.people.length === 0) throw new Error("No invited users");
+ // if (e.people.length === 0) throw new Error("No invited users");
let [fromHour, fromMinute] = e.from_time.split(":");
let [fromYear, fromMonth, fromDay] = e.from_date.split("-");
let [endHour, endMinute] = e.end_time.split(":");
@@ -49,7 +51,7 @@ class HomePage {
};
const data = {
- people: e.people,
+ people: [],
from_date: {
year: Number(fromYear),
month: Number(fromMonth),
@@ -68,6 +70,8 @@ class HomePage {
description: e.description,
location: e.location,
};
+ console.log("data: ", data);
+
return await http.post("/event/", JSON.stringify(data));
} catch (error) {
console.error(
@@ -94,7 +98,7 @@ class HomePage {
!e.date
)
throw new Error("Invalid data");
- if (e.invitedUsers.length === 0) throw new Error("No invited users");
+ // if (e.invitedUsers.length === 0) throw new Error("No invited users");
if (e.invitedUsers.includes(e.hostedUserID))
throw new Error("Hosted user is also invited");
let [hour, minute] = e.time.split(":");
diff --git a/client/src/componants/calendar/CalendarDatePicker.svelte b/client/src/componants/calendar/CalendarDatePicker.svelte
index d0d875dba..9b24699c5 100644
--- a/client/src/componants/calendar/CalendarDatePicker.svelte
+++ b/client/src/componants/calendar/CalendarDatePicker.svelte
@@ -38,6 +38,8 @@
}
function validateDate(date: string): CalenderRequestFormResponseType {
+ console.log("Here....");
+
let validated: CalenderRequestFormResponseType = validateStartEndDates(
date,
startDate,
@@ -48,6 +50,8 @@
calculateActualVacationBalance()
}
errorMessage = validated.message
+ console.log(validated);
+
return validated
}
@@ -89,6 +93,7 @@
}}
size={20}
placeholder={'Start Date'}
+ disabled={true}
/>
{#if !onlyStart}
@@ -103,6 +108,7 @@
}}
size={20}
placeholder={'End Date'}
+ disabled={true}
/>
{/if}
diff --git a/client/src/componants/calendar/EventsCalendar.svelte b/client/src/componants/calendar/EventsCalendar.svelte
deleted file mode 100644
index e69de29bb..000000000
diff --git a/client/src/componants/calendar/forms/EventForm.svelte b/client/src/componants/calendar/forms/EventForm.svelte
index cf97d0641..a8081896e 100644
--- a/client/src/componants/calendar/forms/EventForm.svelte
+++ b/client/src/componants/calendar/forms/EventForm.svelte
@@ -2,21 +2,23 @@
import Input from '../../ui/Input.svelte';
import ModalOpenButton from '../../ui/modals/ModalOpenButton.svelte';
import Modal from '../../ui/modals/SimpleModal.svelte';
- import PeopleSelect from '../../ui/select/UsersMultiSelect.svelte';
+ // import PeopleSelect from '../../ui/select/UsersMultiSelect.svelte';
import type { SelectOptionType, calendarItemsType } from '../../../utils/types';
import CalendarDataService from '../../../apis/home/home';
import Submit from '../../ui/Button.svelte';
import { createEventDispatcher } from 'svelte';
+ import { isValidDate } from '../../../utils/validations';
export let startDate: string;
export let endDate: string;
export let datePickerDisabled = false;
let responseEvent: calendarItemsType;
+ let showToast: boolean = false;
const dispatch = createEventDispatcher();
let modalID = 11988731;
- let eventLocationValue: string;
+ // let eventLocationValue: string;
let eventNameValue: string;
let eventDescriptionValue: string;
let eventFromTimeValue: string;
@@ -25,26 +27,26 @@
let eventDescriptionIsError: boolean | null = null;
let eventFromTimeIsError: boolean | null = null;
let eventEndTimeIsError: boolean | null = null;
- let eventPeopleIsError: boolean | null = null;
+ // let eventPeopleIsError: boolean | null = null;
- let peopleSelected: SelectOptionType[] = [];
+ // let peopleSelected: SelectOptionType[] = [];
let isLoading: boolean = false;
let isError: boolean = false;
// if true the disable submit button
- let locationIsError: boolean | null = null;
- $: fillDisabled =
- locationIsError === null || locationIsError === true || datePickerDisabled;
+ // let locationIsError: boolean | null = null;
+ $: fillDisabled = !isValidDate(startDate) || !isValidDate(endDate)
+ // locationIsError === null || locationIsError === true || datePickerDisabled;
$: submitDisabled =
- fillDisabled === true ||
+ // fillDisabled === true ||
eventNameIsError === null ||
eventNameIsError === true ||
eventDescriptionIsError === null ||
eventDescriptionIsError === true ||
eventFromTimeIsError === true ||
datePickerDisabled ||
- eventEndTimeIsError === true ||
- peopleSelected.length === 0;
+ eventEndTimeIsError === true
+ // peopleSelected.length === 0;
const modalData = {
'data-bs-dismiss': 'modal',
@@ -54,7 +56,7 @@
-
+ /> -->
@@ -79,17 +81,24 @@
isFooter={true}
doneText={'Done'}
deleteText={'Delete'}
+ on:close={() => {
+ eventNameValue = null;
+ eventDescriptionValue = null;
+ eventFromTimeValue = null;
+ eventEndTimeValue = null;
+ eventNameIsError = null;
+ eventDescriptionIsError = null;
+ eventFromTimeIsError = null;
+ eventEndTimeIsError = null;
+ isError = false;
+ }}
>
@@ -160,16 +175,19 @@
errorMessage={eventNameValue + ' Event Submission Failed'}
{modalData}
label="Post Event!"
+ bind:show={showToast}
onClick={async () => {
isLoading = true;
try {
- let selected = peopleSelected.map((item) => Number(item.value));
+ isError = false;
+ // let selected = peopleSelected.map((item) => Number(item.value));
+ // location: eventLocationValue,
const axios = await CalendarDataService.postEvent({
+ location: '',
description: eventDescriptionValue,
end_time: eventEndTimeValue,
- location: eventLocationValue,
name: eventNameValue,
- people: selected,
+ people: [],
end_date: endDate,
from_date: startDate,
from_time: eventFromTimeValue,
@@ -182,11 +200,12 @@
} catch (error) {
isError = true;
} finally {
+ showToast = true;
isLoading = false;
eventDescriptionValue = '';
eventEndTimeValue = '';
- eventLocationValue = '';
- peopleSelected = [];
+ // eventLocationValue = '';
+ // peopleSelected = [];
}
return isError;
}}
diff --git a/client/src/componants/calendar/forms/LeaveForm.svelte b/client/src/componants/calendar/forms/LeaveForm.svelte
index 23cb27f02..fd6ab8c34 100644
--- a/client/src/componants/calendar/forms/LeaveForm.svelte
+++ b/client/src/componants/calendar/forms/LeaveForm.svelte
@@ -32,7 +32,7 @@
$: submitDisabled =
- selectedReason == 0 || datePickerDisabled == true
+ selectedReason == 0 || datePickerDisabled == true || calculatorValue === 0
@@ -55,7 +55,16 @@
{/if}
{#if showCalclator}
- Actual value after deducting weekend holidays {calculatorValue}
+
+ {#if calculatorValue === 0}
+
+ " It seems like the chosen day might be a holiday or a weekend break. Please verify this on your calendar. "
+
+ {:else}
+
+ The final count after excluding weekends and holidays is {calculatorValue} { calculatorValue > 1 ? 'days' : 'day'}.
+
+ {/if}
{/if}
{#if withSubmit}
@@ -67,6 +76,7 @@
onClick={async () => {
isLoading = true;
try {
+ isError = false;
if(isUpdate && vacationID != ""){
const axios = await Vacations.update(vacationID, {
end_date: endDate,
@@ -126,6 +136,9 @@
border-radius: 0.375rem;
transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
+.text-red{
+ color: red;
+}
select{
margin-top: 0.3cm;
background-color: var(--secondary-color);
diff --git a/client/src/componants/calendar/forms/MeetingForm.svelte b/client/src/componants/calendar/forms/MeetingForm.svelte
index b7f3fb136..a4c3e725f 100644
--- a/client/src/componants/calendar/forms/MeetingForm.svelte
+++ b/client/src/componants/calendar/forms/MeetingForm.svelte
@@ -4,12 +4,13 @@
import Submit from '../../ui/Button.svelte';
//import ModalCloseButton from '../modal/ModalCloseButton.svelte';
import Modal from '../../ui/modals/SimpleModal.svelte';
- import PeopleSelect from '../../ui/select/UsersMultiSelect.svelte';
+ // import PeopleSelect from '../../ui/select/UsersMultiSelect.svelte';
import CalendarDataService from '../../../apis/home/home';
import { UserStore } from '../../../utils/stores';
import type { calendarItemsType, SelectOptionType } from '../../../utils/types';
import { createEventDispatcher } from 'svelte';
import { isValidDate } from '../../../utils/validations';
+ // import { isValidDate } from '../../../utils/validations';
export let startDate: string;
export let isError: boolean = false;
@@ -22,8 +23,8 @@
let responseMeeting: calendarItemsType;
const dispatch = createEventDispatcher();
- let meetingLocationValue: string;
- let meetingLocationIsError: boolean | null = null;
+ // let meetingLocationValue: string;
+ // let meetingLocationIsError: boolean | null = null;
let meetingLinkValue: string;
let meetingLinkIsError: boolean | null = null;
let meetingTimeValue: string;
@@ -33,12 +34,10 @@
let peopleSelected: SelectOptionType[] = [];
$: fillDisabled =
- meetingLocationIsError === null ||
- meetingLocationIsError === true ||
+ !isValidDate(startDate) ||
meetingPeopleIsError === null ||
meetingPeopleIsError === true ||
- datePickerDisabled ||
- peopleSelected.length === 0;
+ datePickerDisabled;
let submitDisabled = true;
@@ -47,8 +46,7 @@
meetingLinkIsError === null ||
meetingLinkIsError === true ||
meetingTimeIsError === true ||
- meetingTimeIsError === null ||
- peopleSelected.length === 0;
+ meetingTimeIsError === null;
const modalData = {
'data-bs-dismiss': 'modal',
'data-bs-target': `#modal${modalID}`,
@@ -57,13 +55,13 @@
-
+
{/if}
diff --git a/client/src/componants/ui/modals/CalendarMeetingModel.svelte b/client/src/componants/ui/modals/CalendarMeetingModel.svelte
index 53e67aaef..67e272fa1 100644
--- a/client/src/componants/ui/modals/CalendarMeetingModel.svelte
+++ b/client/src/componants/ui/modals/CalendarMeetingModel.svelte
@@ -82,8 +82,16 @@
@@ -103,12 +111,14 @@
- Invited users
-
- {#each currentMeetingActive.invited_users as user}
-
- {/each}
-
+ {#if currentMeetingActive.invited_users.length}
+ Invited users
+
+ {#each currentMeetingActive.invited_users as user}
+
+ {/each}
+
+ {/if}
{/if}
diff --git a/client/src/componants/ui/modals/SimpleModal.svelte b/client/src/componants/ui/modals/SimpleModal.svelte
index c8fae79b7..8b6e8d981 100644
--- a/client/src/componants/ui/modals/SimpleModal.svelte
+++ b/client/src/componants/ui/modals/SimpleModal.svelte
@@ -11,10 +11,13 @@
let dispatch = createEventDispatcher();
function onDelete() {
- dispatch('onDelete', { id: id });
+ dispatch('delete', { id: id });
+ }
+ function onClose() {
+ dispatch('close', { id: id });
}
function onDone() {
- dispatch('onDone', { id: id });
+ dispatch('done', { id: id });
}
@@ -54,6 +57,7 @@
class="abtn btn-secondary"
data-bs-dismiss="modal"
data-bs-target="#modal"
+ on:click={onClose}
>
{closeText}
diff --git a/client/src/utils/types.ts b/client/src/utils/types.ts
index 2e6cab8d8..f56a14a61 100644
--- a/client/src/utils/types.ts
+++ b/client/src/utils/types.ts
@@ -316,8 +316,8 @@ export type eventItemType = {
location: string;
from_time: string;
end_time: string;
- from_date: Date;
- end_date: Date;
+ from_date: {year: number, month: number, day: number, hour: number, minute: number};
+ end_date: {year: number, month: number, day: number, hour: number, minute: number};
};
export type vacationItemType = {
diff --git a/client/src/utils/validations.ts b/client/src/utils/validations.ts
index 62230743e..0c798b865 100644
--- a/client/src/utils/validations.ts
+++ b/client/src/utils/validations.ts
@@ -51,7 +51,7 @@ export const validateBackgroundColor = (e: any): boolean => {
if (e.target.value[0] == "#" && isNaN(e.target.value.slice(1, -1))) return false;
return true;
}
-
+//
export const validateStartEndDates = (date: string, startDate: string, endDate: string) => {
let response: CalenderRequestFormResponseType = {
message: "Success!",
diff --git a/server/cshr/migrations/0073_alter_event_location_alter_event_people.py b/server/cshr/migrations/0073_alter_event_location_alter_event_people.py
new file mode 100644
index 000000000..7a3d9612b
--- /dev/null
+++ b/server/cshr/migrations/0073_alter_event_location_alter_event_people.py
@@ -0,0 +1,28 @@
+# Generated by Django 4.1.2 on 2023-11-05 07:58
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("cshr", "0072_rename_date_publicholiday_holiday_date_and_more"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="event",
+ name="location",
+ field=models.TextField(max_length=300, null=True),
+ ),
+ migrations.AlterField(
+ model_name="event",
+ name="people",
+ field=models.ManyToManyField(
+ null=True,
+ related_name="event_participants",
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
+ ]
diff --git a/server/cshr/migrations/0074_alter_event_people.py b/server/cshr/migrations/0074_alter_event_people.py
new file mode 100644
index 000000000..5fc0476be
--- /dev/null
+++ b/server/cshr/migrations/0074_alter_event_people.py
@@ -0,0 +1,21 @@
+# Generated by Django 4.1.2 on 2023-11-05 07:59
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("cshr", "0073_alter_event_location_alter_event_people"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="event",
+ name="people",
+ field=models.ManyToManyField(
+ related_name="event_participants", to=settings.AUTH_USER_MODEL
+ ),
+ ),
+ ]
diff --git a/server/cshr/models/event.py b/server/cshr/models/event.py
index c8c189af0..dafb2a3cd 100644
--- a/server/cshr/models/event.py
+++ b/server/cshr/models/event.py
@@ -11,7 +11,7 @@ class Event(TimeStamp):
name = models.CharField(max_length=40)
description = models.CharField(max_length=200)
people = models.ManyToManyField(User, related_name="event_participants")
- location = models.TextField(max_length=300)
+ location = models.TextField(max_length=300, null=True)
from_date = models.DateTimeField(null=True)
end_date = models.DateTimeField(null=True)
diff --git a/server/cshr/serializers/event.py b/server/cshr/serializers/event.py
index 6b0822b97..7261167bd 100644
--- a/server/cshr/serializers/event.py
+++ b/server/cshr/serializers/event.py
@@ -5,24 +5,24 @@
class EventSerializer(ModelSerializer):
- custom_people = SerializerMethodField()
+ # custom_people = SerializerMethodField()
from_date = SerializerMethodField()
end_date = SerializerMethodField()
class Meta:
model = Event
fields = [
- "people",
- "custom_people",
+ # "people",
+ # "custom_people",
"name",
"description",
- "location",
+ # "location",
"from_date",
"end_date",
]
- def get_custom_people(self, obj: Event) -> BaseUserSerializer:
- return BaseUserSerializer(obj.people.all(), many=True).data
+ # def get_custom_people(self, obj: Event) -> BaseUserSerializer:
+ # return BaseUserSerializer(obj.people.all(), many=True).data
def get_from_date(self, obj: Event) -> Dict:
return {
@@ -44,19 +44,19 @@ def get_end_date(self, obj: Event) -> Dict:
class EventOnDaySerializer(ModelSerializer):
- custom_people = SerializerMethodField()
+ # custom_people = SerializerMethodField()
class Meta:
model = Event
fields = [
- "people",
- "custom_people",
+ # "people",
+ # "custom_people",
"name",
"description",
- "location",
+ # "location",
"from_date",
"end_date",
]
- def get_custom_people(self, obj: Event) -> BaseUserSerializer:
- return BaseUserSerializer(obj.people.all(), many=True).data
+ # def get_custom_people(self, obj: Event) -> BaseUserSerializer:
+ # return BaseUserSerializer(obj.people.all(), many=True).data
diff --git a/server/cshr/utils/parse_date.py b/server/cshr/utils/parse_date.py
index fbad311cd..d6a6721c9 100644
--- a/server/cshr/utils/parse_date.py
+++ b/server/cshr/utils/parse_date.py
@@ -1,9 +1,19 @@
"""This file containes parse date function that takes an obj and returns a datetime inctance."""
from typing import Dict, List
-from datetime import datetime
+from datetime import datetime, timedelta
from server.cshr.api.response import CustomResponse
+def get_dates_between_two_dates(start_date, end_date):
+ dates_list = []
+ current_date = start_date
+
+ # Loop through the dates from start_date to end_date
+ while current_date <= end_date:
+ dates_list.append(current_date)
+ current_date += timedelta(days=1)
+
+ return dates_list
class CSHRDate:
def __init__(self, date: Dict) -> None:
diff --git a/server/cshr/utils/vacation_balance_helper.py b/server/cshr/utils/vacation_balance_helper.py
index 4624ff7bd..acd93fb08 100644
--- a/server/cshr/utils/vacation_balance_helper.py
+++ b/server/cshr/utils/vacation_balance_helper.py
@@ -8,6 +8,7 @@
import json
from server.cshr.services.public_holidays import get_user_holidays
+from server.cshr.utils.parse_date import get_dates_between_two_dates
class StanderdVacationBalance:
@@ -145,14 +146,25 @@ def remove_weekends(self, user: User, start_date: datetime, end_date: datetime):
day = start_date + datetime.timedelta(days=i)
if not day.strftime("%A") in weekend:
actual_days.append(day)
- return len(actual_days)
+ print("actual_days list", actual_days)
+ return actual_days
- def remove_holidays(self, user: User, start_date: datetime.datetime, end_date: datetime.datetime, days: int):
+ def remove_holidays(self, user: User, start_date: datetime.datetime, end_date: datetime.datetime, dates: List[datetime.date]):
+ removed_weekends = self.remove_weekends(user, start_date, end_date)
years = [start_date.year, end_date.year]
months = [start_date.month, end_date.month]
holidays = get_user_holidays(user, years, months)
- actual_days = days - len(holidays)
- return actual_days
+ _holydays = 0
+
+ for date in removed_weekends:
+ if date not in dates:
+ dates.append(date)
+
+ for day in holidays:
+ if day.holiday_date in removed_weekends:
+ _holydays += 1
+
+ return len(dates) - _holydays
def vacation_update_balance(self, vacation: Vacation):
"""
@@ -196,15 +208,15 @@ def check_balance(
curr_balance = getattr(v, reason)
if reason == "public_holidays":
return "You cannot apply for public holidays vacations, you take it automatically."
- if old_balance + curr_balance >= vacation_days:
- new_value: int = curr_balance - vacation_days
+ if old_balance + curr_balance >= len(vacation_days):
+ new_value: int = curr_balance - len(vacation_days)
this_month: int = datetime.datetime.now().month
- if old_balance >= vacation_days and this_month < 3:
+ if old_balance >= len(vacation_days) and this_month < 3:
self.set_taked_from_old_balance(vacation)
return self.update_user_balance(
user,
reason,
- old_balance - vacation_days,
+ old_balance - len(vacation_days),
taked_from_old_balance=vacation.taked_from_old_balance,
)
return self.update_user_balance(user, reason, new_value)
diff --git a/server/cshr/views/vacations.py b/server/cshr/views/vacations.py
index 0f56925f9..262030c8b 100644
--- a/server/cshr/views/vacations.py
+++ b/server/cshr/views/vacations.py
@@ -453,4 +453,6 @@ def get(self, request: Request) -> Response:
actual_days: int = v.remove_holidays(
user, converted_from_date, converted_end_date, actual_days
)
+
+ # actual_days = len(actual_days) if actual_days != None else 0
return CustomResponse.success(message="Balance calculated.", data=actual_days)