darta page added
This commit is contained in:
parent
9f6c30541e
commit
67930dfbbb
|
|
@ -10,6 +10,14 @@ const authChildren: Array<RouteRecordRaw> = [
|
|||
permission: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/darta",
|
||||
name: "darta",
|
||||
component: () => import("@/views/Darta/Darta.vue"),
|
||||
meta: {
|
||||
permission: "",
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
export default authChildren;
|
||||
|
|
|
|||
188
src/stores/GenericStore.ts
Normal file
188
src/stores/GenericStore.ts
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
import { defineStore } from "pinia";
|
||||
import Swal from "sweetalert2";
|
||||
import api from "@/services/API/api";
|
||||
import type { Ref } from "vue";
|
||||
import { Toast } from "dolphin-components";
|
||||
|
||||
interface GenericStoreState {
|
||||
errors: Record<string, any>;
|
||||
itemList: [];
|
||||
currentItemDetail: Record<string, any>;
|
||||
payload: Record<string, any>;
|
||||
selectedItems: Record<string, any>;
|
||||
}
|
||||
|
||||
export const createGenericStore = (storeId: string) => {
|
||||
return defineStore(storeId, {
|
||||
state: (): GenericStoreState => ({
|
||||
errors: {},
|
||||
itemList: [],
|
||||
currentItemDetail: {},
|
||||
payload: {},
|
||||
selectedItems: {},
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async fetchList(
|
||||
apiEndpoint: string,
|
||||
params: Record<string, any> = {},
|
||||
loadingRef: Ref<boolean> | null = null
|
||||
): Promise<boolean> {
|
||||
this.errors = {};
|
||||
if (loadingRef) {
|
||||
loadingRef.value = true;
|
||||
}
|
||||
let response = false;
|
||||
try {
|
||||
const apiResponse = await api.get(apiEndpoint, { params });
|
||||
this.itemList = apiResponse.data.data;
|
||||
response = true;
|
||||
} catch (error: any) {
|
||||
this.errors = error?.response?.data?.errors;
|
||||
this.itemList = [];
|
||||
if (error?.response?.status == 403) {
|
||||
Toast.error(
|
||||
error.response.data.detail || "You do not have the permissions to perform this action"
|
||||
);
|
||||
}
|
||||
Toast.error(error?.response?.data?.message || "Error Fetching List");
|
||||
}
|
||||
if (loadingRef) {
|
||||
loadingRef.value = false;
|
||||
}
|
||||
return response;
|
||||
},
|
||||
|
||||
async fetchDetail(
|
||||
apiEndpoint: string,
|
||||
id: number | string,
|
||||
loadingRef: Ref<boolean> | null = null,
|
||||
params: Record<string, any> = {}
|
||||
): Promise<boolean> {
|
||||
this.errors = {};
|
||||
this.currentItemDetail = {};
|
||||
if (loadingRef) loadingRef.value = true;
|
||||
let response = false;
|
||||
try {
|
||||
const apiResponse = await api.get(apiEndpoint + id + "/", { params });
|
||||
this.currentItemDetail = apiResponse.data.data;
|
||||
response = true;
|
||||
} catch (error: any) {
|
||||
this.errors = error?.response?.data?.errors;
|
||||
if (error?.response?.status == 403) {
|
||||
Toast.error(
|
||||
error.response.data.detail || "You do not have the permissions to perform this action"
|
||||
);
|
||||
}
|
||||
Toast.error(error?.response?.data?.message || "Error Fetching Detail");
|
||||
}
|
||||
if (loadingRef) loadingRef.value = false;
|
||||
return response;
|
||||
},
|
||||
|
||||
async createItem(
|
||||
apiEndpoint: string,
|
||||
fetchList: boolean = true,
|
||||
loadingRef: Ref<boolean> | null = null
|
||||
): Promise<any> {
|
||||
this.errors = {};
|
||||
if (loadingRef) loadingRef.value = true;
|
||||
let response: any = false;
|
||||
try {
|
||||
response = await api.post(apiEndpoint, this.payload);
|
||||
if (fetchList) {
|
||||
await this.fetchList(apiEndpoint);
|
||||
}
|
||||
this.resetPayload();
|
||||
if (loadingRef) loadingRef.value = false;
|
||||
} catch (error: any) {
|
||||
this.errors = error?.response?.data?.errors;
|
||||
if (error?.response?.status == 403) {
|
||||
Toast.error(
|
||||
error.response.data.detail || "You do not have the permissions to perform this action"
|
||||
);
|
||||
}
|
||||
if (error?.response?.data?.message != "Validation Error")
|
||||
Toast.error(error?.response?.data?.message || "Error Creating Item");
|
||||
}
|
||||
if (loadingRef) loadingRef.value = false;
|
||||
return response?.data?.data ?? false;
|
||||
},
|
||||
|
||||
async updateItem(
|
||||
apiEndpoint: string,
|
||||
id: number | string,
|
||||
fetchList: boolean = true,
|
||||
loadingRef: Ref<boolean> | null = null
|
||||
): Promise<boolean> {
|
||||
this.errors = {};
|
||||
if (loadingRef) loadingRef.value = true;
|
||||
let response = false;
|
||||
try {
|
||||
await api.patch(apiEndpoint + id + "/", this.payload);
|
||||
response = true;
|
||||
if (fetchList) {
|
||||
await this.fetchList(apiEndpoint);
|
||||
}
|
||||
this.resetPayload();
|
||||
} catch (error: any) {
|
||||
response = false;
|
||||
this.errors = error?.response?.data?.errors;
|
||||
if (error?.response?.status == 403) {
|
||||
Toast.error(
|
||||
error?.response?.data?.detail || "You do not have the permissions to perform this action"
|
||||
);
|
||||
} else if (error?.response?.data?.message != "Validation Error") {
|
||||
Toast.error(error?.response?.data?.message || "Error Updating Item");
|
||||
}
|
||||
}
|
||||
if (loadingRef) loadingRef.value = false;
|
||||
return response;
|
||||
},
|
||||
|
||||
async deleteItem(
|
||||
apiEndpoint: string,
|
||||
id: number | string,
|
||||
fetchList: boolean = true,
|
||||
loadingRef: Ref<boolean> | null = null
|
||||
): Promise<boolean> {
|
||||
const result = await Swal.fire({
|
||||
title: "Delete Confirmation",
|
||||
text: "Are you sure you want to delete this item?",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Confirm",
|
||||
confirmButtonColor: "#004cad",
|
||||
cancelButtonColor: "#9e9e9e",
|
||||
});
|
||||
if (result.isConfirmed) {
|
||||
if (loadingRef) loadingRef.value = true;
|
||||
let response = false;
|
||||
try {
|
||||
await api.delete(apiEndpoint + id + "/");
|
||||
response = true;
|
||||
if (fetchList) {
|
||||
await this.fetchList(apiEndpoint);
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.errors = error?.response?.data?.errors;
|
||||
if (error?.response?.status == 403) {
|
||||
Toast.error(
|
||||
error.response.data.detail || "You do not have the permissions to perform this action"
|
||||
);
|
||||
}
|
||||
Toast.error(error || "Error Deleting Item");
|
||||
}
|
||||
if (loadingRef) loadingRef.value = false;
|
||||
return response;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
resetPayload() {
|
||||
this.payload = {};
|
||||
this.errors = {};
|
||||
this.selectedItems = {};
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
123
src/stores/OverlayStore.ts
Normal file
123
src/stores/OverlayStore.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref, type Ref, onUnmounted } from "vue";
|
||||
import { CreateShortCutKey } from "dolphin-components";
|
||||
|
||||
// We may multiple overlays on top of one another
|
||||
class EscapeKeyManager {
|
||||
private static instance: EscapeKeyManager;
|
||||
private modalStack: Array<() => void> = [];
|
||||
private shortcutHandler: { destroy: () => void } | null = null;
|
||||
|
||||
static getInstance(): EscapeKeyManager {
|
||||
if (!EscapeKeyManager.instance) {
|
||||
EscapeKeyManager.instance = new EscapeKeyManager();
|
||||
}
|
||||
return EscapeKeyManager.instance;
|
||||
}
|
||||
|
||||
addModal(closeCallback: () => void) {
|
||||
this.modalStack.push(closeCallback);
|
||||
|
||||
if (this.modalStack.length === 1) {
|
||||
this.setupEscapeKey();
|
||||
}
|
||||
}
|
||||
|
||||
removeModal(closeCallback: () => void) {
|
||||
const index = this.modalStack.indexOf(closeCallback);
|
||||
if (index > -1) {
|
||||
this.modalStack.splice(index, 1);
|
||||
}
|
||||
|
||||
if (this.modalStack.length === 0) {
|
||||
this.cleanupEscapeKey();
|
||||
}
|
||||
}
|
||||
|
||||
private setupEscapeKey() {
|
||||
if (!this.shortcutHandler) {
|
||||
this.shortcutHandler = CreateShortCutKey("escape", () => {
|
||||
if (this.modalStack.length > 0) {
|
||||
const topModalClose = this.modalStack[this.modalStack.length - 1];
|
||||
if (typeof topModalClose == "function") {
|
||||
topModalClose();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private cleanupEscapeKey() {
|
||||
if (this.shortcutHandler) {
|
||||
this.shortcutHandler.destroy();
|
||||
this.shortcutHandler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const createOverlayStore = (storeId: string) => {
|
||||
return defineStore(storeId, () => {
|
||||
const show = ref(false);
|
||||
const editId = ref<number | string | null>(null);
|
||||
const context = ref<Record<string, any>>({});
|
||||
const escapeManager = EscapeKeyManager.getInstance();
|
||||
let onCloseCallback: (() => void) | null = null;
|
||||
|
||||
function open(options: { id?: number | string; context?: Record<string, any> } = {}) {
|
||||
editId.value = options.id ?? null;
|
||||
context.value = {
|
||||
...context.value,
|
||||
...(options.context || {}),
|
||||
};
|
||||
show.value = true;
|
||||
|
||||
escapeManager.addModal(close);
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (onCloseCallback) {
|
||||
onCloseCallback();
|
||||
}
|
||||
|
||||
show.value = false;
|
||||
editId.value = null;
|
||||
escapeManager.removeModal(close);
|
||||
}
|
||||
|
||||
async function onSave(
|
||||
genericStore: any,
|
||||
genericAPI: any,
|
||||
fetchList: boolean = true,
|
||||
loadingRef: Ref<boolean> | null = null
|
||||
) {
|
||||
let response: any = false;
|
||||
if (editId.value !== null) {
|
||||
response = await genericStore.updateItem(genericAPI, editId.value, fetchList, loadingRef);
|
||||
} else {
|
||||
response = await genericStore.createItem(genericAPI, fetchList, loadingRef);
|
||||
}
|
||||
if (response) close();
|
||||
return response;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (show.value) {
|
||||
escapeManager.removeModal(close);
|
||||
}
|
||||
});
|
||||
|
||||
function setOnCloseCallback(callback: () => void) {
|
||||
onCloseCallback = callback;
|
||||
}
|
||||
|
||||
return {
|
||||
show,
|
||||
editId,
|
||||
context,
|
||||
open,
|
||||
close,
|
||||
onSave,
|
||||
setOnCloseCallback,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import { ref, computed } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useCounterStore = defineStore('counter', () => {
|
||||
const count = ref(0)
|
||||
const doubleCount = computed(() => count.value * 2)
|
||||
function increment() {
|
||||
count.value++
|
||||
}
|
||||
|
||||
return { count, doubleCount, increment }
|
||||
})
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<div class="border border-secondary-100 rounded-xs px-10 py-10 bg-white select-none">
|
||||
<div class="text-center" :class="getLoginError ? '' : 'mb-[10px]'">
|
||||
<p class="text-[30px] text-semibold">Sign In</p>
|
||||
<div class="text-sm font-normal">Fill your detail to sign in to Dolphin DartaChalani.</div>
|
||||
<div class="text-sm font-normal">Fill your detail to sign in to Dolphin Dartachalani.</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-[12px] mb-[-19px]" v-if="getLoginError">
|
||||
|
|
|
|||
33
src/views/Darta/Create.vue
Normal file
33
src/views/Darta/Create.vue
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<template>
|
||||
<Modal :title="modal.title" :actions="modal.action" @onClose="onClose"></Modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
|
||||
const modal = ref({
|
||||
show: false,
|
||||
title: [
|
||||
{
|
||||
name: "Darta",
|
||||
link: "#",
|
||||
},
|
||||
{
|
||||
name: "Create",
|
||||
},
|
||||
],
|
||||
action: [
|
||||
{
|
||||
title: "Close",
|
||||
emit: "onClose",
|
||||
class: "btn-outline",
|
||||
},
|
||||
{
|
||||
title: "Save",
|
||||
emit: "onSave",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const onClose = () => {};
|
||||
</script>
|
||||
98
src/views/Darta/Darta.vue
Normal file
98
src/views/Darta/Darta.vue
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<ContentLayout :title="layout.title" :actions="layout.action" @onCreate="onCreate">
|
||||
<template #body>
|
||||
<div class="content-search">
|
||||
<DateSelector id="report-date" v-model="selectedDate" :classValue="`w-full`" :isBS="true" />
|
||||
</div>
|
||||
<Tabulator
|
||||
:columns="headerDetails"
|
||||
:data="itemList"
|
||||
:heightOffset="250"
|
||||
:action="true"
|
||||
placeholder="No Darta Found"
|
||||
/>
|
||||
</template>
|
||||
</ContentLayout>
|
||||
<Create />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
|
||||
import { BStoAD, NepaliDate } from "nepali-date-library";
|
||||
|
||||
import { storeToRefs } from "pinia";
|
||||
import Create from "@/views/Darta/Create.vue";
|
||||
import { createGenericStore } from "@/stores/GenericStore";
|
||||
import { createOverlayStore } from "@/stores/OverlayStore";
|
||||
import { Toast } from "dolphin-components";
|
||||
|
||||
const DartaStore = createGenericStore("darta")();
|
||||
const DartaModalStore = createOverlayStore("darta-modal")();
|
||||
|
||||
const { itemList } = storeToRefs(DartaStore);
|
||||
|
||||
const layout = ref({
|
||||
title: [
|
||||
{
|
||||
name: "Darta",
|
||||
},
|
||||
],
|
||||
action: [
|
||||
{
|
||||
title: "Create",
|
||||
emit: "onCreate",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// const timeFormatter = (cell: any) => {
|
||||
// const timeStr = cell.getValue();
|
||||
// if (timeStr) {
|
||||
// const [hours, minutes] = timeStr.split(":").map(Number);
|
||||
// const date = new Date(0, 0, 0, hours, minutes);
|
||||
// return date.toLocaleTimeString([], {
|
||||
// hour: "numeric",
|
||||
// minute: "2-digit",
|
||||
// hour12: true,
|
||||
// });
|
||||
// } else {
|
||||
// return cell.getValue();
|
||||
// }
|
||||
// };
|
||||
|
||||
const selectedDate = ref(BStoAD(new NepaliDate().format("YYYY-MM-DD")));
|
||||
|
||||
const headerDetails = [
|
||||
{
|
||||
field: "document_no",
|
||||
title: "Document Number",
|
||||
headerFilter: true,
|
||||
headerFilterPlaceholder: "Search",
|
||||
},
|
||||
{
|
||||
field: "sender_name",
|
||||
title: "Sender",
|
||||
headerFilter: true,
|
||||
headerFilterPlaceholder: "Search",
|
||||
},
|
||||
{
|
||||
field: "receiver_name",
|
||||
title: "Receiver",
|
||||
headerFilter: true,
|
||||
headerFilterPlaceholder: "Search",
|
||||
},
|
||||
{
|
||||
field: "received_date",
|
||||
title: "Received Date",
|
||||
},
|
||||
{
|
||||
field: "is_active",
|
||||
title: "Status",
|
||||
width: "250",
|
||||
},
|
||||
];
|
||||
|
||||
const onCreate = () => {
|
||||
DartaModalStore.open();
|
||||
};
|
||||
</script>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="p-[15px] bg-white relative">
|
||||
<div class="text-[#2f2f2f]">Incoming (Darta)</div>
|
||||
<div class="text-[#2f2f2f]">Darta (Incoming)</div>
|
||||
<div class="text-[24px] text-[#333131]">
|
||||
{{ data.incoming }}
|
||||
</div>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
<div class="p-[15px] bg-white relative">
|
||||
<div class="w-fit">
|
||||
<div class="text-[#2f2f2f]">Outgoing (Chalani)</div>
|
||||
<div class="text-[#2f2f2f]">Chalani (Outgoing)</div>
|
||||
<div class="text-[24px] text-[#333131]">
|
||||
{{ data.outgoing }}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user