Procházet zdrojové kódy

onglet residence area, super admin et educationTimings

Maha Bouchiba před 2 roky
rodič
revize
c57ca9f607

+ 2 - 2
components/Layout/Parameters/Attendances.vue

@@ -16,8 +16,8 @@
           />
 
           <UiInputCheckbox
-            v-model="parameters.notifyAdminOnConsecutiveAbsences"
-            field="notifyAdminOnConsecutiveAbsences"
+            v-model="parameters.notifyAdministrationAbsence"
+            field="notifyAdministrationAbsence"
           />
         </v-col>
       </v-row>

+ 1 - 1
components/Layout/Parameters/CycleEditForm.vue

@@ -38,4 +38,4 @@ const rules = () => [
 
 <style scoped lang="scss">
 
-</style>
+</style>

+ 55 - 0
components/Layout/Parameters/EducationTimings.vue

@@ -0,0 +1,55 @@
+<template>
+  <LayoutContainer>
+    <UiLoadingPanel v-if="pending" />
+    <div v-else>
+      <ul>
+        <li v-for="timing in allTimings" :key="timing.id">  
+          {{  timing.timing  }}
+          <div class="button-group">
+            <UiButtonDelete :model="EducationTiming" :entity="timing" />
+            <span class="edit-icon" @click="goToEditPage(timing.id)">✏️</span>
+          </div>
+        </li>
+      </ul>
+    </div>
+    <button @click="goToCreatePage">Nouveau</button>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
+import EducationTiming from '~/models/Education/EducationTiming'
+import {useRepo} from "pinia-orm";
+import EducationTimingsRepository from '~/stores/repositories/EducationTimingsRepository';
+
+const { fetchCollection } = useEntityFetch()
+
+const { data: educationTimings, pending } = fetchCollection(EducationTiming)
+
+const educationTimingRepo = useRepo(EducationTimingsRepository);
+
+const allTimings: ComputedRef<Array<EducationTiming>> = computed(() => {
+  return educationTimingRepo.getEducationTimings()
+})
+
+console.log(allTimings)
+
+
+const goToEditPage = (id: number) => {
+  navigateTo(`/parameters/education_timings/${id}`)
+}
+
+const goToCreatePage = () => {
+  navigateTo(`/parameters/education_timings/new`)
+}
+</script>
+
+<style scoped lang="scss">
+.button-group {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  gap: 8px;  
+}
+
+</style>

+ 49 - 0
components/Layout/Parameters/ResidenceAreas.vue

@@ -0,0 +1,49 @@
+<template>
+  <LayoutContainer>
+    <UiLoadingPanel v-if="pending" />
+    <div v-else>
+      <!-- Afficher la liste des résidences -->
+      <ul>
+        <li v-for="area in allResidenceArea" :key="area.id">
+          {{ area.label }}
+          <UiButtonDelete :model="ResidenceArea" :entity="area" />
+          <span class="edit-icon" @click="goToEditPage(area.id)">✏️</span>
+        </li>
+      </ul>
+    </div>
+    <button @click="goToCreatePage">Nouveau</button>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
+import ResidenceArea from '~/models/Billing/ResidenceArea'
+import { useRepo } from 'pinia-orm'
+import ResidenceAreasRepository from '~/stores/repositories/ResidenceAreasRepository'
+import { useRouter } from 'vue-router'
+const residenceAreasRepo = useRepo(ResidenceAreasRepository)
+
+const router = useRouter()
+const { fetchCollection } = useEntityFetch()
+const i18n = useI18n()
+
+const { data: residence_areas, pending } = fetchCollection(ResidenceArea)
+
+/**
+ * On récupère les Residence Area via le store 
+ * (sans ça, les mises à jour SSE ne seront pas prises en compte)
+ */
+ const allResidenceArea: ComputedRef<Array<ResidenceArea>> = computed(() => {
+  return residenceAreasRepo.getResidenceAreas()
+})
+
+const goToEditPage = (id: number) => {
+  navigateTo(`/parameters/residence_areas/${id}`)
+}
+
+const goToCreatePage = () => {
+  navigateTo(`/parameters/residence_areas/new`)
+}
+</script>
+
+<style scoped lang="scss"></style>

+ 34 - 26
components/Layout/Parameters/SuperAdmin.vue

@@ -1,42 +1,50 @@
 <template>
+  <div>superadmin email</div>
+
   <div>
-    <div class="mb-4">
-      Le compte super-admin possède tous les droits de gestion sur votre
-      logiciel. On l’utilise surtout pour la gestion de votre site internet et,
-      à la première connexion au logiciel, afin de créer des comptes pour tous
-      membres de votre structure. Enfin, il peut également être utile en cas de
-      dépannage dans certaines situations particulières.
-    </div>
-
-    <UiForm :model="parameters" :entity="Parameters">
-      <v-row>
-        <v-col cols="12">
+    <LayoutContainer>
+      <UiLoadingPanel v-if="pending" />
+
+      <div v-else>
+        <UiForm
+          ref="form"
+          :model="AdminAccess"
+          :entity="adminAccess"
+          :submitActions="submitActions"
+        >
           <UiInputText
-            v-model="parameters.superAdminEmail"
-            field="superAdminEmail"
+            field="label"
+            v-model="adminAccess.email"
+            :rules="rules()"
           />
-        </v-col>
-      </v-row>
-    </UiForm>
+        </UiForm>
+      </div>
+    </LayoutContainer>
   </div>
 </template>
 
 <script setup lang="ts">
-import Parameters from '~/models/Organization/Parameters'
 import { useEntityFetch } from '~/composables/data/useEntityFetch'
-import { useOrganizationProfileStore } from '~/stores/organizationProfile'
-import { AsyncData } from '#app'
+import { useAccessProfileStore } from '~/stores/accessProfile'
+import AdminAccess from '~/models/Access/AdminAccess'
 
 const { fetch } = useEntityFetch()
 
-const organizationProfile = useOrganizationProfileStore()
+const accessProfile = useAccessProfileStore()
+
+const id = accessProfile.id
+console.log(id)
 
-if (organizationProfile.parametersId === null) {
-  throw new Error('Missing organization parameters id')
+if (accessProfile.id === null) {
+  throw new Error('Missing access profile id')
 }
 
-const { data: parameters, pending } = fetch(
-  Parameters,
-  organizationProfile.parametersId
-) as AsyncData<Parameters, Parameters | true>
+const { data: adminAccess, pending } = fetch(AdminAccess, id)
+
+const i18n = useI18n()
+
+const rules = () => [
+  (label: string | null) =>
+    (label !== null && label.length > 0) || i18n.t('please_enter_a_value'),
+]
 </script>

+ 1 - 0
components/Layout/Parameters/Website.vue

@@ -144,6 +144,7 @@ const { data: subdomains, pending: subdomainsPending } = fetchCollection(Subdoma
 const canAddNewSubdomain: ComputedRef<boolean> = computed(() => subdomains.value && subdomains.value.items.length < 3)
 
 const goToEditPage = (id: number) => {
+  console.log(parameters.value)
   navigateTo(`parameters/subdomains/${id}`)
 }
 

+ 3 - 2
components/Ui/Button/Delete.vue

@@ -55,9 +55,10 @@ const { em } = useEntityManager()
 const deleteItem = async () => {
   try {
     await em.delete(props.model, props.entity)
-    usePageStore().addAlerts(TYPE_ALERT.SUCCESS, ['deleteSuccess'])
+    usePageStore().addAlert(TYPE_ALERT.SUCCESS, ['deleteSuccess'])
   } catch (error: any) {
-    usePageStore().addAlerts(TYPE_ALERT.ALERT, [error.message])
+    usePageStore().addAlert(TYPE_ALERT.ALERT, [error.message])
+    throw error
   }
   showDialog.value = false
 }

+ 1 - 1
lang/fr.json

@@ -182,7 +182,7 @@
   "usernameSMS": "Nom d'utilisateur SMS",
   "smsSenderName": "Personnaliser le nom de l'expéditeur SMS",
   "attendance": "Absences",
-  "notifyAdminOnConsecutiveAbsences": "Prévenir l'administrateur en cas d'absences consécutives",
+  "notifyAdministrationAbsence": "Prévenir l'administrateur en cas d'absences consécutives",
   "sendAttendanceEmail": "Prévenir automatiquement la famille par mail en cas d'absence non justifiée",
   "sendAttendanceSms": "Prévenir automatiquement la famille par sms en cas d'absence non justifiée",
   "bulletinReceiver": "Adresser le bulletin à",

+ 1 - 1
models/Access/AdminAccess.ts

@@ -5,7 +5,7 @@ import ApiResource from "~/models/ApiResource";
  * @see https://gitlab.2iopenservice.com/opentalent/ap2i/-/blob/develop/src/ApiResources/Access/AdminAccess.php
  */
 export default class AdminAccess extends ApiResource {
-  static entity = 'admin'
+  static entity = 'admin-access'
 
   @Uid()
   declare id: number

+ 1 - 4
models/Organization/Parameters.ts

@@ -120,9 +120,6 @@ export default class Parameters extends ApiModel {
   @Attr([])
   declare subdomains: []
 
-  @Str(null)
-  declare superAdminEmail: string | null
-
   @Bool(false, { notNullable: true })
-  declare notifyAdminOnConsecutiveAbsences: boolean
+  declare notifyAdministrationAbsence: boolean 
 }

+ 45 - 0
pages/parameters/education_timings/[id].vue

@@ -0,0 +1,45 @@
+<template>
+  <LayoutContainer>
+    <UiLoadingPanel v-if="pending" />
+    <div v-else>
+      <h2> EducationTiming</h2>
+      <UiForm
+        ref="form"
+        :model="EducationTiming"
+        :entity="education_timings"
+        :submitActions="submitActions"
+      >
+      <UiInputNumber field="educationtiming" v-model="education_timings.timing" />
+      </UiForm>
+    </div>
+  </LayoutContainer>
+</template>
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
+import EducationTiming from '~/models/Education/EducationTiming';
+import { useRoute } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+import {AnyJson} from "~/types/data";
+import {SUBMIT_TYPE} from "~/types/enum/enums";
+
+const goBackRoute = { path: `/parameters`, query: { tab: 'educationTimings' } }
+
+const i18n = useI18n()
+const { fetch } = useEntityFetch()
+const route = useRoute()
+const id = ref(route.params.id)
+console.log(id.value) 
+
+const submitActions = computed(() => {
+  let actions: AnyJson = {}
+  actions[SUBMIT_TYPE.SAVE_AND_BACK] = goBackRoute
+  return actions
+})
+
+
+const {data : education_timings, pending} = fetch(EducationTiming, id.value)
+console.log(education_timings)
+
+
+</script>

+ 58 - 0
pages/parameters/education_timings/new.vue

@@ -0,0 +1,58 @@
+<template>
+  <LayoutContainer>
+    <UiLoadingPanel v-if="pending" />
+    <div v-else>
+      <h2>Créer Nouvelle Education Timing</h2>
+      <UiForm
+        ref="form"
+        :model="EducationTiming"
+        :entity="education_timings"
+        :submitActions="submitActions"
+      >
+      <v-container :fluid="true" class="container">
+          <v-row>
+            <v-col cols="12" sm="6">
+            </v-col>
+          </v-row>
+          <v-row>
+            <v-col cols="12" sm="6">
+              <UiInputNumber
+                  v-model="education_timings.timing"
+                  field="education_timings"
+              />
+            </v-col>
+          </v-row>
+        </v-container>
+      </UiForm>
+    </div>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+import {Ref} from "@vue/reactivity";
+import {AnyJson} from "~/types/data";
+import {SUBMIT_TYPE} from "~/types/enum/enums";
+import EducationTiming from '~/models/Education/EducationTiming'
+import { useI18n } from 'vue-i18n'
+import { useEntityManager } from '~/composables/data/useEntityManager'
+
+const i18n = useI18n()
+
+const { em } = useEntityManager()
+
+const education_timings: Ref<EducationTiming> = ref(em.newInstance(EducationTiming) as EducationTiming)
+
+const goBackRoute = { path: `/parameters`, query: { tab: 'educationTimings' } }
+
+
+const submitActions = computed(() => {
+  let actions: AnyJson = {}
+  actions[SUBMIT_TYPE.SAVE_AND_BACK] = goBackRoute
+  return actions
+})
+
+const rules = () => [
+  (label: string | null) => (label !== null && label.length > 0) || i18n.t('please_enter_a_value'),
+]
+</script>

+ 3 - 0
pages/parameters/index.vue

@@ -44,6 +44,7 @@ Page Paramètres
           </v-window-item>
 
           <v-window-item v-if="organizationProfile.isSchool" value="educationTimings">
+            <LayoutParametersEducationTimings />
           </v-window-item>
 
           <v-window-item v-if="organizationProfile.isSchool" value="attendances">
@@ -51,6 +52,7 @@ Page Paramètres
           </v-window-item>
 
           <v-window-item v-if="organizationProfile.isSchool" value="residenceAreas">
+            <LayoutParametersResidenceAreas />
           </v-window-item>
 
           <v-window-item v-if="organizationProfile.hasModule('Sms')" value="sms_option">
@@ -127,3 +129,4 @@ Page Paramètres
   letter-spacing: 0.04em;
 }
 </style>
+

+ 48 - 0
pages/parameters/residence_areas/[id].vue

@@ -0,0 +1,48 @@
+<template>
+  <LayoutContainer>
+    <UiLoadingPanel v-if="pending" />
+    <div v-else>
+      <h2> Editer la zone de résidence</h2>
+      <UiForm
+        ref="form"
+        :model="ResidenceArea"
+        :entity="residence_areas"
+        :submitActions="submitActions"
+      >
+      <UiInputText field="label" v-model="residence_areas.label" :rules="rules()"  />
+      </UiForm>
+
+    </div>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted } from 'vue'
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
+import ResidenceArea from '~/models/Billing/ResidenceArea'
+import { useRoute } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+import {AnyJson} from "~/types/data";
+import {SUBMIT_TYPE} from "~/types/enum/enums";
+
+const i18n = useI18n()
+const { fetch } = useEntityFetch()
+const route = useRoute()
+const id = ref(route.params.id)
+
+const goBackRoute = { path: `/parameters`, query: { tab: 'residenceAreas' } }
+const submitActions = computed(() => {
+  let actions: AnyJson = {}
+  actions[SUBMIT_TYPE.SAVE_AND_BACK] = goBackRoute
+  return actions
+})
+
+
+
+const {data : residence_areas, pending} = fetch(ResidenceArea, id.value)
+
+const rules = () => [
+  (label: string | null) =>
+    (label !== null && label.length > 0) || i18n.t('please_enter_a_value'),
+]
+</script>

+ 62 - 0
pages/parameters/residence_areas/new.vue

@@ -0,0 +1,62 @@
+<template>
+  <LayoutContainer>
+    <UiLoadingPanel v-if="pending" />
+    <div v-else>
+      <h2>Créer Nouvelle Résidence Area</h2>
+      <UiForm
+        ref="form"
+        :model="ResidenceArea"
+        :entity="residence_areas"
+        :submitActions="submitActions"
+      >
+      <v-container :fluid="true" class="container">
+          <v-row>
+            <v-col cols="12" sm="6">
+              <div>{{ $t('pleaseEnterYourNewSubdomain')}} :</div>
+            </v-col>
+          </v-row>
+          <v-row>
+            <v-col cols="12" sm="6">
+              <UiInputText
+                  v-model="residence_areas.label"
+                  field="residence Areas"
+                  type="string"
+                  :rules="rules()"
+              />
+            </v-col>
+          </v-row>
+        </v-container>
+      </UiForm>
+    </div>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, computed } from 'vue'
+import {Ref} from "@vue/reactivity";
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
+import {AnyJson} from "~/types/data";
+import {SUBMIT_TYPE} from "~/types/enum/enums";
+import ResidenceArea from '~/models/Billing/ResidenceArea'
+import { useI18n } from 'vue-i18n'
+import { useEntityManager } from '~/composables/data/useEntityManager'
+
+const i18n = useI18n()
+
+const { em } = useEntityManager()
+
+const residence_areas: Ref<ResidenceArea> = ref(em.newInstance(ResidenceArea) as ResidenceArea)
+
+const goBackRoute = { path: `/parameters`, query: { tab: 'residenceAreas' } }
+
+
+const submitActions = computed(() => {
+  let actions: AnyJson = {}
+  actions[SUBMIT_TYPE.SAVE_AND_BACK] = goBackRoute
+  return actions
+})
+
+const rules = () => [
+  (label: string | null) => (label !== null && label.length > 0) || i18n.t('please_enter_a_value'),
+]
+</script>

+ 2 - 1
services/data/entityManager.ts

@@ -266,6 +266,7 @@ class EntityManager {
      * @param instance
      */
     public async delete(model: typeof ApiModel, instance: ApiResource) {
+
         const repository = this.getRepository(model)
 
         // If object has been persisted to the datasource, send a delete request
@@ -273,7 +274,7 @@ class EntityManager {
             const url = UrlUtils.join('api', model.entity, String(instance.id))
             await this.apiRequestService.delete(url)
         }
-
+        console.log(repository.all())
         // reactiveUpdate the store
         repository.destroy(instance.id)
     }

+ 18 - 0
stores/repositories/EducationTimingsRepository.ts

@@ -0,0 +1,18 @@
+import {Collection} from "pinia-orm";
+import EducationTiming from "~/models/Education/EducationTiming";
+import BaseRepository from "~/stores/repositories/BaseRepository";
+
+class EducationTimingsRepository extends BaseRepository {
+    use = EducationTiming
+
+    /**
+     * On récupère les EducationTimings via le store
+     */
+    public getEducationTimings(): Collection<EducationTiming> {
+        return this.getQuery()
+            .get() as Collection<EducationTiming>
+    }
+
+}
+
+export default EducationTimingsRepository

+ 16 - 0
stores/repositories/ResidenceAreasRepository.ts

@@ -0,0 +1,16 @@
+import { Collection } from 'pinia-orm'
+import ResidenceArea from '~/models/Billing/ResidenceArea'
+import BaseRepository from '~/stores/repositories/BaseRepository'
+
+class ResidenceAreasRepository extends BaseRepository {
+  use = ResidenceArea
+
+  /**
+   * On récupère les Notifications via le store
+   */
+  public getResidenceAreas(): Collection<ResidenceArea> {
+    return this.getQuery().get() as Collection<ResidenceArea>
+  }
+}
+
+export default ResidenceAreasRepository