|
@@ -4,6 +4,14 @@
|
|
|
class="q-dialog-plugin overflow-hidden"
|
|
class="q-dialog-plugin overflow-hidden"
|
|
|
style="width: 100%; max-width: 1100px"
|
|
style="width: 100%; max-width: 1100px"
|
|
|
>
|
|
>
|
|
|
|
|
+ <input
|
|
|
|
|
+ ref="signedFileInputRef"
|
|
|
|
|
+ accept="image/jpeg,image/png,.pdf"
|
|
|
|
|
+ style="display: none"
|
|
|
|
|
+ type="file"
|
|
|
|
|
+ @change="onSignedFileSelected"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
<DefaultDialogHeader
|
|
<DefaultDialogHeader
|
|
|
title="Histórico do Contrato"
|
|
title="Histórico do Contrato"
|
|
|
@close="onDialogCancel"
|
|
@close="onDialogCancel"
|
|
@@ -92,6 +100,28 @@
|
|
|
}}
|
|
}}
|
|
|
</q-tooltip>
|
|
</q-tooltip>
|
|
|
</q-btn>
|
|
</q-btn>
|
|
|
|
|
+
|
|
|
|
|
+ <q-btn
|
|
|
|
|
+ v-if="row.signed_file_url || canEdit"
|
|
|
|
|
+ class="q-ml-xs"
|
|
|
|
|
+ outline
|
|
|
|
|
+ style="width: 36px"
|
|
|
|
|
+ :icon="
|
|
|
|
|
+ row.signed_file_url
|
|
|
|
|
+ ? 'mdi-file-check-outline'
|
|
|
|
|
+ : 'mdi-file-upload-outline'
|
|
|
|
|
+ "
|
|
|
|
|
+ :loading="uploadingSignedId === row.id"
|
|
|
|
|
+ @click="handleSignedContractFile(row)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <q-tooltip>
|
|
|
|
|
+ {{
|
|
|
|
|
+ row.signed_file_url
|
|
|
|
|
+ ? "Visualizar contrato assinado desta versão"
|
|
|
|
|
+ : "Enviar contrato assinado desta versão"
|
|
|
|
|
+ }}
|
|
|
|
|
+ </q-tooltip>
|
|
|
|
|
+ </q-btn>
|
|
|
</q-td>
|
|
</q-td>
|
|
|
</template>
|
|
</template>
|
|
|
</q-table>
|
|
</q-table>
|
|
@@ -111,12 +141,14 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { computed, onMounted, ref } from "vue";
|
|
|
|
|
-import { getUnitPackagesForSelect } from "src/api/package";
|
|
|
|
|
import {
|
|
import {
|
|
|
|
|
+ attachSignedContractFile,
|
|
|
generateStudentContractFile,
|
|
generateStudentContractFile,
|
|
|
getStudentContractById,
|
|
getStudentContractById,
|
|
|
} from "src/api/studentContract";
|
|
} from "src/api/studentContract";
|
|
|
|
|
+
|
|
|
|
|
+import { computed, onMounted, ref } from "vue";
|
|
|
|
|
+import { getUnitPackagesForSelect } from "src/api/package";
|
|
|
import { permissionStore } from "src/stores/permission";
|
|
import { permissionStore } from "src/stores/permission";
|
|
|
import { useDialogPluginComponent, useQuasar } from "quasar";
|
|
import { useDialogPluginComponent, useQuasar } from "quasar";
|
|
|
|
|
|
|
@@ -144,8 +176,12 @@ const permissions = permissionStore();
|
|
|
const contract = ref(null);
|
|
const contract = ref(null);
|
|
|
const loading = ref(false);
|
|
const loading = ref(false);
|
|
|
const generatingId = ref(null);
|
|
const generatingId = ref(null);
|
|
|
|
|
+const signedFileInputRef = ref(null);
|
|
|
|
|
+const uploadingSignedId = ref(null);
|
|
|
const packages = ref([]);
|
|
const packages = ref([]);
|
|
|
|
|
|
|
|
|
|
+let pendingSignedContractId = null;
|
|
|
|
|
+
|
|
|
const canEdit = computed(() =>
|
|
const canEdit = computed(() =>
|
|
|
permissions.getAccess("franchisee_contracts", "edit"),
|
|
permissions.getAccess("franchisee_contracts", "edit"),
|
|
|
);
|
|
);
|
|
@@ -229,6 +265,8 @@ const historyRows = computed(() =>
|
|
|
.sort((first, second) => Number(second.version) - Number(first.version)),
|
|
.sort((first, second) => Number(second.version) - Number(first.version)),
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
const formatCurrency = (value) =>
|
|
const formatCurrency = (value) =>
|
|
|
new Intl.NumberFormat("pt-BR", {
|
|
new Intl.NumberFormat("pt-BR", {
|
|
|
currency: "BRL",
|
|
currency: "BRL",
|
|
@@ -246,22 +284,6 @@ const formatDateTime = (value) => {
|
|
|
return `${day}/${month}/${year}${time ? ` ${time.slice(0, 5)}` : ""}`;
|
|
return `${day}/${month}/${year}${time ? ` ${time.slice(0, 5)}` : ""}`;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const statusColor = (status) => {
|
|
|
|
|
- if (status === "active") return "positive";
|
|
|
|
|
- if (status === "frozen") return "info";
|
|
|
|
|
- if (status === "cancelled") return "negative";
|
|
|
|
|
-
|
|
|
|
|
- return "warning";
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const statusLabel = (status) => {
|
|
|
|
|
- if (status === "active") return "Ativo";
|
|
|
|
|
- if (status === "frozen") return "Trancado";
|
|
|
|
|
- if (status === "cancelled") return "Cancelado";
|
|
|
|
|
-
|
|
|
|
|
- return "Inativo";
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
const handleContractFile = async (row) => {
|
|
const handleContractFile = async (row) => {
|
|
|
if (row.file_url) {
|
|
if (row.file_url) {
|
|
|
window.open(row.file_url, "_blank", "noopener,noreferrer");
|
|
window.open(row.file_url, "_blank", "noopener,noreferrer");
|
|
@@ -306,6 +328,84 @@ const handleContractFile = async (row) => {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
|
|
+const handleSignedContractFile = (row) => {
|
|
|
|
|
+ if (row.signed_file_url) {
|
|
|
|
|
+ window.open(row.signed_file_url, "_blank", "noopener,noreferrer");
|
|
|
|
|
+
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pendingSignedContractId = row.id;
|
|
|
|
|
+
|
|
|
|
|
+ signedFileInputRef.value.value = "";
|
|
|
|
|
+ signedFileInputRef.value.click();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const onSignedFileSelected = async (event) => {
|
|
|
|
|
+ const file = event.target.files?.[0];
|
|
|
|
|
+
|
|
|
|
|
+ const contractId = pendingSignedContractId;
|
|
|
|
|
+
|
|
|
|
|
+ if (!file || !contractId) return;
|
|
|
|
|
+
|
|
|
|
|
+ uploadingSignedId.value = contractId;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const formData = new FormData();
|
|
|
|
|
+
|
|
|
|
|
+ formData.append("file", file);
|
|
|
|
|
+
|
|
|
|
|
+ const updated = await attachSignedContractFile(contractId, formData);
|
|
|
|
|
+
|
|
|
|
|
+ const version = contract.value?.version_history?.find(
|
|
|
|
|
+ (item) => item.id === contractId,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (version) {
|
|
|
|
|
+ version.signed_file_url = updated.signed_file_url;
|
|
|
|
|
+ version.signed_file_type = updated.signed_file_type;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $q.notify({
|
|
|
|
|
+ message: "Contrato assinado enviado com sucesso.",
|
|
|
|
|
+ type: "positive",
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error(error);
|
|
|
|
|
+
|
|
|
|
|
+ $q.notify({
|
|
|
|
|
+ message: "Erro ao enviar o contrato assinado.",
|
|
|
|
|
+ type: "negative",
|
|
|
|
|
+ });
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ pendingSignedContractId = null;
|
|
|
|
|
+
|
|
|
|
|
+ uploadingSignedId.value = null;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
|
|
+const statusColor = (status) => {
|
|
|
|
|
+ if (status === "active") return "positive";
|
|
|
|
|
+ if (status === "frozen") return "info";
|
|
|
|
|
+ if (status === "cancelled") return "negative";
|
|
|
|
|
+
|
|
|
|
|
+ return "warning";
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const statusLabel = (status) => {
|
|
|
|
|
+ if (status === "active") return "Ativo";
|
|
|
|
|
+ if (status === "frozen") return "Trancado";
|
|
|
|
|
+ if (status === "cancelled") return "Cancelado";
|
|
|
|
|
+
|
|
|
|
|
+ return "Inativo";
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
|
|
|