| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <template>
- <q-page class="dashboard-page bg-page">
- <template v-if="loading">
- <div
- class="bg-surface full-width items-center justify-center row"
- style="height: 80vh"
- >
- <q-spinner-dots color="primary" />
- </div>
- </template>
- <template v-else>
- <q-pull-to-refresh color="primary" @refresh="onRefresh">
- <DashboardHeaderBar :data="headerBar" :notifications="notifications" />
- <DashboardSummaryInfos :data="summaryInfos" />
- <DashboardPendingApproval v-if="isPendingProvider" />
- <template v-else>
- <DashboardPriceSuggest :data="priceSuggestion" />
- <DashboardTodayServices
- v-if="todayServices?.length > 0"
- :data="todayServices"
- @refresh="loadDashboard"
- @rate="openRatingDialog"
- @view-details="openScheduleOnCalendar"
- />
- <DashboardScrollAreaSchedules />
- <DashboardSolicitations
- v-if="solicitations?.length > 0"
- :data="solicitations"
- @accept="(item) => openDetailsDialog(item)"
- @reject="(item) => openDetailsDialog(item, 'confirm-reject')"
- @view-details="(item) => openDetailsDialog(item)"
- />
- <DashboardPendingConfirmation
- v-if="pendingConfirmation.length > 0"
- :data="pendingConfirmation"
- @view-details="(item) => openNextScheduleDialog(item)"
- />
- <DashboardNextSchedules
- :data="nextSchedules"
- @view-details="(item) => openNextScheduleDialog(item)"
- />
- <DashboardOpportunities :data="opportunities" />
- </template>
- </q-pull-to-refresh>
- </template>
- </q-page>
- </template>
- <script setup>
- import { dadosDashboard } from "src/api/dashboard";
- import { onMounted, onUnmounted, ref, watch } from "vue";
- import { acceptServicePackage, rejectServicePackage, updateScheduleStatus } from "src/api/schedule";
- import { useI18n } from "vue-i18n";
- import { useQuasar } from "quasar";
- import { useAuth } from "src/composables/useAuth";
- import { useProviderApproval } from "src/composables/useProviderApproval";
- import { useRoute, useRouter } from "vue-router";
- import DashboardHeaderBar from "src/components/dashboard/DashboardHeaderBar.vue";
- import DashboardNextSchedules from "src/components/dashboard/DashboardNextSchedules.vue";
- import DashboardOpportunities from "src/components/dashboard/DashboardOpportunities.vue";
- import DashboardPendingApproval from "src/components/dashboard/DashboardPendingApproval.vue";
- import DashboardPriceSuggest from "src/components/dashboard/DashboardPriceSuggest.vue";
- import DashboardScrollAreaSchedules from "src/components/dashboard/DashboardScrollAreaSchedules.vue";
- import DashboardSolicitations from "src/components/dashboard/DashboardSolicitations.vue";
- import DashboardSummaryInfos from "src/components/dashboard/DashboardSummaryInfos.vue";
- import DashboardTodayServices from "src/components/dashboard/DashboardTodayServices.vue";
- import NextSchedulesDetailsDialog from "src/components/dashboard/NextSchedulesDetailsDialog.vue";
- import ScheduleRatingDialog from "src/components/dashboard/ScheduleRatingDialog.vue";
- import SolicitationDetailsDialog from "src/components/dashboard/SolicitationDetailsDialog.vue";
- import ProposalAcceptedDialog from "src/components/dashboard/ProposalAcceptedDialog.vue";
- import OpportunityDialog from "src/pages/opportunities/components/OpportunityDialog.vue";
- import DashboardPendingConfirmation from "src/components/dashboard/DashboardPendingConfirmation.vue";
- const $q = useQuasar();
- const router = useRouter();
- const route = useRoute();
- const { t } = useI18n();
- const { refreshApprovalStatus } = useAuth();
- const { isPendingProvider } = useProviderApproval();
- // Enquanto o cadastro está em análise, reconsulta a aprovação periodicamente
- // para liberar a dashboard completa sem exigir novo login.
- const APPROVAL_POLL_INTERVAL_MS = 3 * 60 * 1000;
- let approvalPollId = null;
- const headerBar = ref({});
- const loading = ref(true);
- const nextSchedules = ref([]);
- const notifications = ref([]);
- const opportunities = ref([]);
- const priceSuggestion = ref({});
- const solicitations = ref([]);
- const summaryInfos = ref({});
- const todayServices = ref([]);
- const pendingConfirmation = ref([]);
- const handleScheduleAction = async (id, status, ids = [], servicePackageId = null) => {
- try {
- if (servicePackageId && status === "accepted") {
- await acceptServicePackage(servicePackageId);
- } else if (servicePackageId && status === "rejected") {
- await rejectServicePackage(servicePackageId);
- } else {
- const scheduleIds = ids.length ? ids : [id];
- await Promise.all(
- scheduleIds.map((scheduleId) => updateScheduleStatus(scheduleId, status)),
- );
- }
- } catch (e) {
- console.log(e);
- } finally {
- await loadDashboard();
- }
- };
- const loadDashboard = async () => {
- const response = await dadosDashboard();
- if (response) {
- headerBar.value = response.headerBar;
- nextSchedules.value = response.nextSchedules ?? [];
- notifications.value = response.notifications ?? [];
- opportunities.value = response.opportunities ?? [];
- priceSuggestion.value = response.priceSuggested;
- solicitations.value = response.solicitations ?? [];
- summaryInfos.value = response.summaryInfos;
- pendingConfirmation.value = response.pendingConfirmation ?? [];
- todayServices.value = response.todayServices ?? [];
- }
- };
- const checkApprovalStatus = async () => {
- if (!isPendingProvider.value) {
- return false;
- }
- try {
- const approved = await refreshApprovalStatus();
- if (!approved) {
- return false;
- }
- stopApprovalPolling();
- $q.notify({
- message: t("provider.dashboard.pending_approval.approved"),
- type: "positive",
- });
- await loadDashboard();
- return true;
- } catch (error) {
- console.error(error);
- return false;
- }
- };
- const startApprovalPolling = () => {
- if (approvalPollId || !isPendingProvider.value) {
- return;
- }
- approvalPollId = setInterval(checkApprovalStatus, APPROVAL_POLL_INTERVAL_MS);
- };
- const stopApprovalPolling = () => {
- if (!approvalPollId) {
- return;
- }
- clearInterval(approvalPollId);
- approvalPollId = null;
- };
- const onRefresh = async (done) => {
- try {
- const approved = await checkApprovalStatus();
- if (!approved) {
- await loadDashboard();
- }
- } finally {
- done();
- }
- };
- const openDetailsDialog = (solicitation, initialView = "details") => {
- $q.dialog({
- component: SolicitationDetailsDialog,
- componentProps: { initialView, solicitation },
- }).onOk(async ({ action, id, ids, service_package_id } = {}) => {
- if (action === "cancelled") {
- await loadDashboard();
- return;
- }
- await handleScheduleAction(
- id,
- action === "accept" ? "accepted" : "rejected",
- ids,
- service_package_id,
- );
- if (action === "accept") {
- $q.dialog({
- component: ProposalAcceptedDialog,
- });
- }
- });
- };
- const openNextScheduleDialog = (schedule) => {
- $q.dialog({
- component: NextSchedulesDetailsDialog,
- componentProps: { schedule },
- }).onOk(async ({ action }) => {
- if (action === "cancelled") {
- await loadDashboard();
- }
- });
- };
- const openScheduleOnCalendar = (schedule) => {
- router.push({
- name: "CalendarPage",
- query: { scheduleId: schedule.id },
- });
- };
- const openRatingDialog = (schedule) => {
- $q.dialog({
- component: ScheduleRatingDialog,
- componentProps: { schedule },
- }).onOk(() => {
- loadDashboard();
- });
- };
- watch(
- () => route.query.approved,
- async (val) => {
- if (val !== "true") {
- return;
- }
- stopApprovalPolling();
- if (!loading.value) {
- await loadDashboard();
- }
- $q.notify({
- message: t("provider.dashboard.pending_approval.approved"),
- type: "positive",
- });
- router.replace({ path: route.path, query: {} });
- },
- { immediate: true },
- );
- watch(
- () => route.query.showSuccessModal,
- async (val) => {
- if (val === "true") {
- if (!loading.value) {
- await loadDashboard();
- }
- $q.dialog({ component: OpportunityDialog }).onDismiss(() => {
- router.replace({ path: route.path, query: {} });
- });
- }
- },
- { immediate: true },
- );
- onMounted(async () => {
- await loadDashboard();
- loading.value = false;
- startApprovalPolling();
- });
- onUnmounted(() => {
- stopApprovalPolling();
- });
- </script>
- <style scoped>
- .dashboard-page {
- box-sizing: border-box;
- min-height: 100%;
- width: 100%;
- }
- </style>
|