Initial commit.
This commit is contained in:
		
						commit
						2d11d0bd79
					
				
					 54 changed files with 6657 additions and 0 deletions
				
			
		
							
								
								
									
										162
									
								
								src/pages/FormFillPage.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/pages/FormFillPage.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,162 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <q-page padding>
 | 
			
		||||
    <q-inner-loading :showing="loading">
 | 
			
		||||
      <q-spinner-gears size="50px" color="primary" />
 | 
			
		||||
    </q-inner-loading>
 | 
			
		||||
 | 
			
		||||
    <div v-if="!loading && form">
 | 
			
		||||
      <div class="text-h4 q-mb-xs">{{ form.title }}</div>
 | 
			
		||||
      <div class="text-subtitle1 text-grey q-mb-lg">{{ form.description }}</div>
 | 
			
		||||
 | 
			
		||||
      <q-form @submit.prevent="submitResponse" class="q-gutter-md">
 | 
			
		||||
 | 
			
		||||
        <div v-for="category in form.categories" :key="category.id" class="q-mb-lg">
 | 
			
		||||
          <div class="text-h6 q-mb-sm">{{ category.name }}</div>
 | 
			
		||||
          <div v-for="field in category.fields" :key="field.id" class="q-mb-md">
 | 
			
		||||
            <q-item-label class="q-mb-xs">{{ field.label }}</q-item-label>
 | 
			
		||||
            <q-item-label caption v-if="field.description" class="q-mb-xs text-grey-7">{{ field.description }}</q-item-label>
 | 
			
		||||
            <q-input
 | 
			
		||||
              v-if="field.type === 'text'"
 | 
			
		||||
              outlined
 | 
			
		||||
              v-model="responses[field.id]"
 | 
			
		||||
              :label="field.label"
 | 
			
		||||
            />
 | 
			
		||||
            <q-input
 | 
			
		||||
              v-else-if="field.type === 'number'"
 | 
			
		||||
              outlined
 | 
			
		||||
              type="number"
 | 
			
		||||
              v-model.number="responses[field.id]"
 | 
			
		||||
              :label="field.label"
 | 
			
		||||
            />
 | 
			
		||||
             <q-input
 | 
			
		||||
              v-else-if="field.type === 'date'"
 | 
			
		||||
              outlined
 | 
			
		||||
              type="date"
 | 
			
		||||
              v-model="responses[field.id]"
 | 
			
		||||
              :label="field.label"
 | 
			
		||||
              stack-label
 | 
			
		||||
            />
 | 
			
		||||
            <q-input
 | 
			
		||||
              v-else-if="field.type === 'textarea'"
 | 
			
		||||
              outlined
 | 
			
		||||
              type="textarea"
 | 
			
		||||
              autogrow
 | 
			
		||||
              v-model="responses[field.id]"
 | 
			
		||||
              :label="field.label"
 | 
			
		||||
            />
 | 
			
		||||
            <q-checkbox
 | 
			
		||||
              v-else-if="field.type === 'boolean'"
 | 
			
		||||
              v-model="responses[field.id]"
 | 
			
		||||
              :label="field.label"
 | 
			
		||||
              left-label
 | 
			
		||||
              class="q-mt-sm"
 | 
			
		||||
            />
 | 
			
		||||
            <!-- Add other field types as needed -->
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <q-separator class="q-my-lg" />
 | 
			
		||||
 | 
			
		||||
        <div>
 | 
			
		||||
          <q-btn outline label="Submit Response" type="submit" color="primary" :loading="submitting"/>
 | 
			
		||||
          <q-btn outline label="Cancel" type="reset" color="default" class="q-ml-sm" :to="{ name: 'formList' }" />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
      </q-form>
 | 
			
		||||
    </div>
 | 
			
		||||
     <q-banner v-else-if="!loading && !form" class="bg-negative text-white">
 | 
			
		||||
      <template v-slot:avatar>
 | 
			
		||||
        <q-icon name="error" />
 | 
			
		||||
      </template>
 | 
			
		||||
      Form not found or could not be loaded.
 | 
			
		||||
      <template v-slot:action>
 | 
			
		||||
        <q-btn flat color="white" label="Back to Forms" :to="{ name: 'formList' }" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </q-banner>
 | 
			
		||||
  </q-page>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted, reactive } from 'vue';
 | 
			
		||||
import axios from 'axios';
 | 
			
		||||
import { useQuasar } from 'quasar';
 | 
			
		||||
import { useRouter, useRoute } from 'vue-router';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  id: {
 | 
			
		||||
    type: [String, Number],
 | 
			
		||||
    required: true
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const $q = useQuasar();
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
const route = useRoute();
 | 
			
		||||
const form = ref(null);
 | 
			
		||||
const responses = reactive({}); // Use reactive for dynamic properties
 | 
			
		||||
const loading = ref(true);
 | 
			
		||||
const submitting = ref(false);
 | 
			
		||||
 | 
			
		||||
async function fetchFormDetails() {
 | 
			
		||||
  loading.value = true;
 | 
			
		||||
  form.value = null; // Reset form data
 | 
			
		||||
  try {
 | 
			
		||||
    const response = await axios.get(`/api/forms/${props.id}`);
 | 
			
		||||
    form.value = response.data;
 | 
			
		||||
    // Initialize responses object based on fields
 | 
			
		||||
    form.value.categories.forEach(cat => {
 | 
			
		||||
      cat.fields.forEach(field => {
 | 
			
		||||
        responses[field.id] = null; // Initialize all fields to null or default
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error(`Error fetching form ${props.id}:`, error);
 | 
			
		||||
    $q.notify({
 | 
			
		||||
      color: 'negative',
 | 
			
		||||
      position: 'top',
 | 
			
		||||
      message: 'Failed to load form details.',
 | 
			
		||||
      icon: 'report_problem'
 | 
			
		||||
    });
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function submitResponse() {
 | 
			
		||||
  submitting.value = true;
 | 
			
		||||
  try {
 | 
			
		||||
    // Basic check if any response is provided (optional)
 | 
			
		||||
    // const hasResponse = Object.values(responses).some(val => val !== null && val !== '');
 | 
			
		||||
    // if (!hasResponse) {
 | 
			
		||||
    //   $q.notify({ color: 'warning', message: 'Please fill in at least one field.' });
 | 
			
		||||
    //   return;
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    await axios.post(`/api/forms/${props.id}/responses`, { values: responses });
 | 
			
		||||
    $q.notify({
 | 
			
		||||
      color: 'positive',
 | 
			
		||||
      position: 'top',
 | 
			
		||||
      message: 'Response submitted successfully!',
 | 
			
		||||
      icon: 'check_circle'
 | 
			
		||||
    });
 | 
			
		||||
    // Optionally redirect or clear form
 | 
			
		||||
    router.push({ name: 'formResponses', params: { id: props.id } }); // Go to responses page after submit
 | 
			
		||||
    // Or clear the form:
 | 
			
		||||
    // Object.keys(responses).forEach(key => { responses[key] = null; });
 | 
			
		||||
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('Error submitting response:', error);
 | 
			
		||||
    const message = error.response?.data?.error || 'Failed to submit response.';
 | 
			
		||||
    $q.notify({
 | 
			
		||||
      color: 'negative',
 | 
			
		||||
      position: 'top',
 | 
			
		||||
      message: message,
 | 
			
		||||
      icon: 'report_problem'
 | 
			
		||||
    });
 | 
			
		||||
  } finally {
 | 
			
		||||
    submitting.value = false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(fetchFormDetails);
 | 
			
		||||
</script>
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue