Skip to content

Commit

Permalink
Merge pull request #6053 from christianbeeznest/GH-6048
Browse files Browse the repository at this point in the history
Attendance: Improve attendance tool with Vue & Symfony integration - refs #6048
  • Loading branch information
christianbeeznest authored Feb 13, 2025
2 parents 2117d33 + 5238e55 commit 1baf8e1
Show file tree
Hide file tree
Showing 36 changed files with 3,190 additions and 36 deletions.
64 changes: 64 additions & 0 deletions assets/css/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,70 @@ form .field {
}
}

.attendance-page {
canvas {
width: 100%;
height: 100%;
display: block;
}

tr {
height: 100px;
}

th,
td {
height: 100px;
vertical-align: middle;
}

.flex {
display: flex;
}

.flex-col {
flex-direction: column;
}

.align-middle {
vertical-align: middle;
}

.mt-1 {
margin-top: 4px;
}

.gap-2 {
gap: 8px;
}

.opacity-50 {
opacity: 0.5;
}

.cursor-not-allowed {
cursor: not-allowed;
}

.loader {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}

.row {
@apply flex flex-wrap -mx-4;
}
Expand Down
156 changes: 156 additions & 0 deletions assets/vue/components/attendance/AttendanceCalendarForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<template>
<form class="flex flex-col gap-6 mt-6">
<!-- Start Date -->
<BaseCalendar
v-model="formData.startDate"
:label="t('Start Date')"
:show-time="true"
required
/>

<!-- Repeat Date -->
<BaseCheckbox
v-model="formData.repeatDate"
:label="t('Repeat Date')"
@change="toggleRepeatOptions"
/>

<div v-if="formData.repeatDate">
<!-- Repeat Type -->
<BaseSelect
v-model="formData.repeatType"
:label="t('Repeat Type')"
:options="repeatTypeOptions"
option-label="label"
option-value="value"
required
/>

<!-- Number of Days for Every X Days -->
<div v-if="formData.repeatType === 'every-x-days'">
<BaseInputNumber
v-model="formData.repeatDays"
:label="t('Number of days')"
type="number"
min="1"
required
/>
</div>

<!-- Repeat End Date -->
<BaseCalendar
v-model="formData.repeatEndDate"
:label="t('Repeat End Date')"
:show-time="true"
required
/>
</div>

<!-- Group -->
<BaseSelect
v-model="formData.group"
:label="t('Group')"
:options="groupOptions"
option-label="label"
option-value="value"
required
/>

<!-- Buttons -->
<LayoutFormButtons>
<BaseButton
:label="t('Back')"
icon="arrow-left"
type="black"
@click="$emit('back-pressed')"
/>
<BaseButton
:label="t('Save')"
icon="check"
type="success"
@click="submitForm"
/>
</LayoutFormButtons>
</form>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue"
import { useI18n } from "vue-i18n"
import attendanceService from "../../services/attendanceService"
import BaseCalendar from "../../components/basecomponents/BaseCalendar.vue"
import BaseCheckbox from "../../components/basecomponents/BaseCheckbox.vue"
import BaseSelect from "../../components/basecomponents/BaseSelect.vue"
import LayoutFormButtons from "../../components/layout/LayoutFormButtons.vue"
import BaseButton from "../../components/basecomponents/BaseButton.vue"
import { useRoute } from "vue-router"
import BaseInputNumber from "../basecomponents/BaseInputNumber.vue"
const { t } = useI18n()
const emit = defineEmits(["back-pressed"])
const route = useRoute()
const parentResourceNodeId = ref(Number(route.params.node))
const formData = reactive({
startDate: "",
repeatDate: false,
repeatType: "",
repeatEndDate: "",
repeatDays: 0,
group: "",
})
const repeatTypeOptions = [
{ label: t("Daily"), value: "daily" },
{ label: t("Weekly"), value: "weekly" },
{ label: t("Bi-Weekly"), value: "bi-weekly" },
{ label: t("Every X Days"), value: "every-x-days" },
{ label: t("Monthly by Date"), value: "monthly-by-date" },
]
const groupOptions = ref([])
const toggleRepeatOptions = () => {
if (!formData.repeatDate) {
formData.repeatType = ""
formData.repeatEndDate = ""
formData.repeatDays = 0
}
}
const submitForm = async () => {
if (!formData.startDate) {
return
}
if (formData.repeatDate && (!formData.repeatType || !formData.repeatEndDate)) {
return
}
const payload = {
startDate: formData.startDate,
repeatDate: formData.repeatDate,
repeatType: formData.repeatType,
repeatEndDate: formData.repeatEndDate,
repeatDays: formData.repeatType === "every-x-days" ? formData.repeatDays : null,
group: formData.group ? parseInt(formData.group) : null,
}
try {
await attendanceService.addAttendanceCalendar(route.params.id, payload)
emit("back-pressed")
} catch (error) {
console.error("Error adding attendance calendar entry:", error)
}
}
const loadGroups = async () => {
try {
groupOptions.value = await attendanceService.fetchGroups(parentResourceNodeId.value)
} catch (error) {
console.error("Error loading groups:", error)
}
}
onMounted(loadGroups)
</script>
Loading

0 comments on commit 1baf8e1

Please sign in to comment.