darta page added
This commit is contained in:
parent
9f6c30541e
commit
67930dfbbb
|
|
@ -10,6 +10,14 @@ const authChildren: Array<RouteRecordRaw> = [
|
||||||
permission: "",
|
permission: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/darta",
|
||||||
|
name: "darta",
|
||||||
|
component: () => import("@/views/Darta/Darta.vue"),
|
||||||
|
meta: {
|
||||||
|
permission: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default authChildren;
|
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="border border-secondary-100 rounded-xs px-10 py-10 bg-white select-none">
|
||||||
<div class="text-center" :class="getLoginError ? '' : 'mb-[10px]'">
|
<div class="text-center" :class="getLoginError ? '' : 'mb-[10px]'">
|
||||||
<p class="text-[30px] text-semibold">Sign In</p>
|
<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>
|
||||||
|
|
||||||
<div class="mt-[12px] mb-[-19px]" v-if="getLoginError">
|
<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>
|
</div>
|
||||||
<div class="p-[15px] bg-white relative">
|
<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]">
|
<div class="text-[24px] text-[#333131]">
|
||||||
{{ data.incoming }}
|
{{ data.incoming }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="p-[15px] bg-white relative">
|
<div class="p-[15px] bg-white relative">
|
||||||
<div class="w-fit">
|
<div class="w-fit">
|
||||||
<div class="text-[#2f2f2f]">Outgoing (Chalani)</div>
|
<div class="text-[#2f2f2f]">Chalani (Outgoing)</div>
|
||||||
<div class="text-[24px] text-[#333131]">
|
<div class="text-[24px] text-[#333131]">
|
||||||
{{ data.outgoing }}
|
{{ data.outgoing }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user