Просмотр исходного кода

feat(packages): add class duration input and weekday selection to AddEditPackageDialog; update PackageCard to display default class duration

ebagabee 1 неделя назад
Родитель
Сommit
175af661eb

+ 126 - 0
src/pages/packages/components/AddEditPackageDialog.vue

@@ -32,6 +32,73 @@
                   min="0"
                   min="0"
                 />
                 />
 
 
+                <q-banner class="col-12 bg-blue-1 text-primary rounded-borders">
+                  A duração padrão das aulas é de 2 horas e pode ser alterada se
+                  necessário. É possível configurar no máximo dois dias.
+                </q-banner>
+
+                <DefaultInput
+                  v-model="form.class_duration_hours"
+                  label="Duração da Aula (horas)"
+                  class="col-12"
+                  type="number"
+                  min="0.5"
+                  max="24"
+                  step="0.5"
+                />
+
+                <DefaultSelect
+                  v-model="form.weekday"
+                  label="1º Dia da Semana"
+                  class="col-4"
+                  :options="weekdays"
+                  option-value="value"
+                  option-label="label"
+                  emit-value
+                  map-options
+                  clearable
+                />
+
+                <DefaultInput
+                  v-model="form.start_time"
+                  label="Horário Inicial"
+                  class="col-4"
+                  mask="##:##"
+                />
+
+                <DefaultInput
+                  :model-value="firstEndTime"
+                  label="Horário Final"
+                  class="col-4"
+                  disable
+                />
+
+                <DefaultSelect
+                  v-model="form.second_weekday"
+                  label="2º Dia da Semana"
+                  class="col-4"
+                  :options="secondWeekdayOptions"
+                  option-value="value"
+                  option-label="label"
+                  emit-value
+                  map-options
+                  clearable
+                />
+
+                <DefaultInput
+                  v-model="form.second_start_time"
+                  label="Horário Inicial do 2º dia"
+                  class="col-4"
+                  mask="##:##"
+                />
+
+                <DefaultInput
+                  :model-value="secondEndTime"
+                  label="Horário Final do 2º dia"
+                  class="col-4"
+                  disable
+                />
+
                 <DefaultCurrencyInput
                 <DefaultCurrencyInput
                   v-model="form.contract_register_value"
                   v-model="form.contract_register_value"
                   label="R$ Matrícula"
                   label="R$ Matrícula"
@@ -431,6 +498,30 @@ const tabs = [
 
 
 const products = ref([]);
 const products = ref([]);
 
 
+const weekdays = [
+  { value: 1, label: "Segunda" },
+  { value: 2, label: "Terça" },
+  { value: 3, label: "Quarta" },
+  { value: 4, label: "Quinta" },
+  { value: 5, label: "Sexta" },
+  { value: 6, label: "Sábado" },
+  { value: 0, label: "Domingo" },
+];
+
+const trimTime = (time) => (time ? time.slice(0, 5) : null);
+
+const calculateEndTime = (startTime, durationHours) => {
+  if (!/^\d{2}:\d{2}$/.test(startTime ?? "")) return null;
+  const [hours, minutes] = startTime.split(":").map(Number);
+  if (hours > 23 || minutes > 59) return null;
+  const end =
+    (hours * 60 + minutes + Math.round(Number(durationHours) * 60)) %
+    (24 * 60);
+  return `${String(Math.floor(end / 60)).padStart(2, "0")}:${String(
+    end % 60,
+  ).padStart(2, "0")}`;
+};
+
 const productOptions = computed(() =>
 const productOptions = computed(() =>
   products.value.map((p) => ({
   products.value.map((p) => ({
     label: p.name,
     label: p.name,
@@ -445,9 +536,37 @@ const form = ref({
   contract_register_value: props.package?.contract_register_value ?? null,
   contract_register_value: props.package?.contract_register_value ?? null,
   contract_value: props.package?.contract_value ?? null,
   contract_value: props.package?.contract_value ?? null,
   contrat_discount_value: props.package?.contrat_discount_value ?? null,
   contrat_discount_value: props.package?.contrat_discount_value ?? null,
+  class_duration_hours:
+    (props.package?.class_duration_minutes ?? 120) / 60,
+  weekday: props.package?.weekday ?? null,
+  start_time: trimTime(props.package?.start_time),
+  second_weekday: props.package?.second_weekday ?? null,
+  second_start_time: trimTime(props.package?.second_start_time),
   materials: [{ product_id: null, quantity: 1, price: null }],
   materials: [{ product_id: null, quantity: 1, price: null }],
 });
 });
 
 
+const secondWeekdayOptions = computed(() =>
+  weekdays.filter((day) => day.value !== form.value.weekday),
+);
+const firstEndTime = computed(() =>
+  calculateEndTime(form.value.start_time, form.value.class_duration_hours),
+);
+const secondEndTime = computed(() =>
+  calculateEndTime(
+    form.value.second_start_time,
+    form.value.class_duration_hours,
+  ),
+);
+
+watch(
+  () => form.value.weekday,
+  (weekday) => {
+    if (form.value.second_weekday === weekday) {
+      form.value.second_weekday = null;
+    }
+  },
+);
+
 const onProductSelected = (material) => {
 const onProductSelected = (material) => {
   const option = productOptions.value.find(
   const option = productOptions.value.find(
     (o) => o.value === material.product_id,
     (o) => o.value === material.product_id,
@@ -600,6 +719,13 @@ const onOKClick = async () => {
       contract_value: form.value.contract_value,
       contract_value: form.value.contract_value,
       contract_register_value: form.value.contract_register_value,
       contract_register_value: form.value.contract_register_value,
       contrat_discount_value: form.value.contrat_discount_value,
       contrat_discount_value: form.value.contrat_discount_value,
+      class_duration_minutes: Math.round(
+        Number(form.value.class_duration_hours) * 60,
+      ),
+      weekday: form.value.weekday,
+      start_time: form.value.start_time || null,
+      second_weekday: form.value.second_weekday,
+      second_start_time: form.value.second_start_time || null,
       group_ids: groups.value
       group_ids: groups.value
         .filter((g) => g.visible)
         .filter((g) => g.visible)
         .map((g) => g.id),
         .map((g) => g.id),

+ 3 - 0
src/pages/packages/components/PackageCard.vue

@@ -8,6 +8,9 @@
     <q-card-section class="q-pa-md">
     <q-card-section class="q-pa-md">
       <div class="text-subtitle1 text-weight-bold">{{ pkg.name }}</div>
       <div class="text-subtitle1 text-weight-bold">{{ pkg.name }}</div>
       <div class="text-body2 text-grey-6 q-mb-sm">{{ pkg.quantity_classes }} Aulas</div>
       <div class="text-body2 text-grey-6 q-mb-sm">{{ pkg.quantity_classes }} Aulas</div>
+      <div class="text-body2 text-grey-6 q-mb-sm">
+        Duração padrão: {{ (pkg.class_duration_minutes ?? 120) / 60 }}h
+      </div>
 
 
       <div class="column" style="gap: 2px">
       <div class="column" style="gap: 2px">
         <span class="text-body2">Contrato {{ formatToBRLCurrency(pkg.contract_value) }}</span>
         <span class="text-body2">Contrato {{ formatToBRLCurrency(pkg.contract_value) }}</span>