From a01cd6f1bf34e876e5fed5ecf59f3603eabdf1ae Mon Sep 17 00:00:00 2001 From: namdh Date: Sun, 20 Sep 2026 16:17:33 +0700 Subject: [PATCH] feat: add Logs --- src/composables/useTheme.ts | 31 ----- src/layouts/AdminLayout.vue | 20 ++- src/layouts/MainLayout.vue | 12 +- src/main.ts | 2 +- src/router/index.ts | 2 + src/services/backend.ts | 14 ++ src/types/index.ts | 43 ++++++ src/views/auth/LoginView.vue | 12 -- .../settings/actionlogs/ActionLogsView.vue | 122 +++++++++++++++++ .../settings/loginlogs/LoginLogsView.vue | 127 ++++++++++++++++++ .../settings/permissions/PermissionsView.vue | 2 + src/views/tasks/TasksBoardView.vue | 39 +++++- 12 files changed, 353 insertions(+), 73 deletions(-) delete mode 100644 src/composables/useTheme.ts create mode 100644 src/views/settings/actionlogs/ActionLogsView.vue create mode 100644 src/views/settings/loginlogs/LoginLogsView.vue diff --git a/src/composables/useTheme.ts b/src/composables/useTheme.ts deleted file mode 100644 index b28caa0..0000000 --- a/src/composables/useTheme.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { ref, watch } from 'vue' - -const STORAGE_KEY = 'mws_theme' -const DARK_CLASS = 'app-dark' - -const isDark = ref(loadInitial()) - -function loadInitial(): boolean { - const stored = localStorage.getItem(STORAGE_KEY) - if (stored === 'dark') return true - if (stored === 'light') return false - return window.matchMedia('(prefers-color-scheme: dark)').matches -} - -function apply(value: boolean) { - document.documentElement.classList.toggle(DARK_CLASS, value) -} - -apply(isDark.value) - -watch(isDark, (value) => { - apply(value) - localStorage.setItem(STORAGE_KEY, value ? 'dark' : 'light') -}) - -export function useTheme() { - function toggle() { - isDark.value = !isDark.value - } - return { isDark, toggle } -} diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue index da6fe72..5c1f86d 100644 --- a/src/layouts/AdminLayout.vue +++ b/src/layouts/AdminLayout.vue @@ -46,7 +46,7 @@ Users -
+
@@ -88,20 +94,12 @@ />
-
-
+
@@ -112,12 +110,10 @@ diff --git a/src/views/settings/loginlogs/LoginLogsView.vue b/src/views/settings/loginlogs/LoginLogsView.vue new file mode 100644 index 0000000..720863b --- /dev/null +++ b/src/views/settings/loginlogs/LoginLogsView.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/views/settings/permissions/PermissionsView.vue b/src/views/settings/permissions/PermissionsView.vue index e2c4b99..c13fe02 100644 --- a/src/views/settings/permissions/PermissionsView.vue +++ b/src/views/settings/permissions/PermissionsView.vue @@ -117,6 +117,8 @@ const ALL_SCREENS = [ { key: 'users', label: 'Users' }, { key: 'permissions', label: 'Permissions' }, { key: 'masterdata', label: 'Master Data' }, + { key: 'actionlogs', label: 'Action Logs' }, + { key: 'loginlogs', label: 'Login Logs' }, ] const filteredRoles = computed(() => { diff --git a/src/views/tasks/TasksBoardView.vue b/src/views/tasks/TasksBoardView.vue index 833c833..b34786e 100644 --- a/src/views/tasks/TasksBoardView.vue +++ b/src/views/tasks/TasksBoardView.vue @@ -54,14 +54,15 @@ My task
{{ task.description }}
-
- +
+ {{ task.assigneeName }} -
-
- - {{ formatDate(task.dueDate) }} + + {{ task.dueDate ? formatDate(task.dueDate) : 'No Due date' }}
@@ -275,6 +276,32 @@ watch( font-weight: 600; line-height: 1.5; } +.meta-chip { + display: inline-flex; + align-items: center; + gap: 0.25rem; + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 999px; + padding: 2px 8px; + font-size: 0.72rem; + font-weight: 500; + line-height: 1.5; +} +.meta-chip-user { + background: var(--primary-soft); + color: var(--primary); +} +.meta-chip-due { + background: rgba(245, 158, 11, 0.14); + color: #b45309; +} +.meta-chip-nodue { + background: rgba(110, 107, 102, 0.1); + color: var(--ink-muted); +} .board-col.drag-over { background: color-mix(in srgb, var(--primary) 6%, transparent); box-shadow: inset 0 0 0 2px var(--primary);