diff --git a/src/router/authChildren.ts b/src/router/authChildren.ts index 07c05ac..c0d35e9 100644 --- a/src/router/authChildren.ts +++ b/src/router/authChildren.ts @@ -10,6 +10,14 @@ const authChildren: Array = [ permission: "", }, }, + { + path: "/darta", + name: "darta", + component: () => import("@/views/Darta/Darta.vue"), + meta: { + permission: "", + }, + } ]; export default authChildren; diff --git a/src/stores/GenericStore.ts b/src/stores/GenericStore.ts new file mode 100644 index 0000000..0009247 --- /dev/null +++ b/src/stores/GenericStore.ts @@ -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; + itemList: []; + currentItemDetail: Record; + payload: Record; + selectedItems: Record; +} + +export const createGenericStore = (storeId: string) => { + return defineStore(storeId, { + state: (): GenericStoreState => ({ + errors: {}, + itemList: [], + currentItemDetail: {}, + payload: {}, + selectedItems: {}, + }), + + actions: { + async fetchList( + apiEndpoint: string, + params: Record = {}, + loadingRef: Ref | null = null + ): Promise { + 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 | null = null, + params: Record = {} + ): Promise { + 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 | null = null + ): Promise { + 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 | null = null + ): Promise { + 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 | null = null + ): Promise { + 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 = {}; + }, + }, + }); +}; diff --git a/src/stores/OverlayStore.ts b/src/stores/OverlayStore.ts new file mode 100644 index 0000000..1e5c263 --- /dev/null +++ b/src/stores/OverlayStore.ts @@ -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(null); + const context = ref>({}); + const escapeManager = EscapeKeyManager.getInstance(); + let onCloseCallback: (() => void) | null = null; + + function open(options: { id?: number | string; context?: Record } = {}) { + 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 | 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, + }; + }); +}; diff --git a/src/stores/counter.ts b/src/stores/counter.ts deleted file mode 100644 index b6757ba..0000000 --- a/src/stores/counter.ts +++ /dev/null @@ -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 } -}) diff --git a/src/views/Auth/Login.vue b/src/views/Auth/Login.vue index 0e1b1c8..306a80a 100644 --- a/src/views/Auth/Login.vue +++ b/src/views/Auth/Login.vue @@ -7,7 +7,7 @@

Sign In

-
Fill your detail to sign in to Dolphin DartaChalani.
+
Fill your detail to sign in to Dolphin Dartachalani.
diff --git a/src/views/Darta/Create.vue b/src/views/Darta/Create.vue new file mode 100644 index 0000000..f20ce40 --- /dev/null +++ b/src/views/Darta/Create.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/views/Darta/Darta.vue b/src/views/Darta/Darta.vue new file mode 100644 index 0000000..8d5d68d --- /dev/null +++ b/src/views/Darta/Darta.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/Dashboard/Components/Dashboard.vue b/src/views/Dashboard/Components/Dashboard.vue index 7bc597f..648c061 100644 --- a/src/views/Dashboard/Components/Dashboard.vue +++ b/src/views/Dashboard/Components/Dashboard.vue @@ -8,7 +8,7 @@
-
Incoming (Darta)
+
Darta (Incoming)
{{ data.incoming }}
@@ -19,7 +19,7 @@
-
Outgoing (Chalani)
+
Chalani (Outgoing)
{{ data.outgoing }}