-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
-> Migrating to laravel
- Loading branch information
Showing
5 changed files
with
234 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
165 changes: 111 additions & 54 deletions
165
frontend/src/components/client/Dashboard/Account/Activities.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,126 @@ | ||
<script setup lang="ts"> | ||
import LayoutAccount from './Layout.vue'; | ||
import TableTanstack from '@/components/client/ui/Table/TableTanstack.vue'; | ||
import { format } from 'date-fns'; | ||
import { ref, onMounted, onErrorCaptured } from 'vue' | ||
import axios from 'axios' | ||
import { format } from 'date-fns' | ||
import LayoutAccount from './Layout.vue' | ||
const Activities = [ | ||
{ | ||
action: 'Login', | ||
description: 'User logged in', | ||
ip_address: '127.0.0.1', | ||
date: '2023-10-01', | ||
}, | ||
{ | ||
action: 'Logout', | ||
description: 'User logged out', | ||
ip_address: '127.0.0.1', | ||
date: '2023-10-01', | ||
}, | ||
{ | ||
action: 'Login', | ||
description: 'User logged in', | ||
ip_address: '127.0.0.1', | ||
date: '2023-10-01', | ||
}, | ||
]; | ||
const columnsActivities = [ | ||
{ | ||
accessorKey: 'action', | ||
header: 'Action', | ||
}, | ||
{ | ||
accessorKey: 'description', | ||
header: 'Description', | ||
}, | ||
{ | ||
accessorKey: 'ip_address', | ||
header: 'Ip Address', | ||
}, | ||
{ | ||
accessorKey: 'date', | ||
header: 'Created', | ||
cell: (info: { getValue: () => string | number | Date }) => format(new Date(info.getValue()), 'MMM d, yyyy'), | ||
}, | ||
]; | ||
interface Activity { | ||
id: number | ||
user: string | ||
action: string | ||
ip_address: string | ||
deleted: string | ||
locked: string | ||
date: string | ||
} | ||
interface ActivityResponse { | ||
code: number | ||
error: null | string | ||
message: string | ||
success: boolean | ||
activities: Activity[] | ||
} | ||
const activities = ref<Activity[]>([]) | ||
const loading = ref(true) | ||
const error = ref<string | null>(null) | ||
const fetchActivities = async () => { | ||
try { | ||
console.log('Fetching activities...') | ||
const response = await axios.get<ActivityResponse>('/api/user/session/activities') | ||
console.log('Response received:', response.data) | ||
if (response.data.success) { | ||
activities.value = response.data.activities | ||
console.log('Activities loaded:', activities.value) | ||
} else { | ||
throw new Error(response.data.error || 'Failed to fetch activities') | ||
} | ||
} catch (err) { | ||
console.error('Error fetching activities:', err) | ||
error.value = err instanceof Error ? err.message : 'An unknown error occurred' | ||
} finally { | ||
loading.value = false | ||
} | ||
} | ||
onMounted(() => { | ||
console.log('Component mounted') | ||
fetchActivities() | ||
}) | ||
onErrorCaptured((err) => { | ||
console.error('Error captured:', err) | ||
error.value = 'An unexpected error occurred' | ||
return false | ||
}) | ||
const columns = [ | ||
{ key: 'id', title: 'ID' }, | ||
{ key: 'action', title: 'Action' }, | ||
{ key: 'ip_address', title: 'IP Address' }, | ||
{ key: 'date', title: 'Date' }, | ||
{ key: 'deleted', title: 'Deleted' }, | ||
{ key: 'locked', title: 'Locked' }, | ||
] | ||
const formatDate = (date: string) => format(new Date(date), 'MMM d, yyyy HH:mm:ss') | ||
</script> | ||
<template> | ||
<!-- User Info --> | ||
<LayoutAccount /> | ||
|
||
<div> | ||
<div class="overflow-x-auto"> | ||
<TableTanstack :data="Activities" :columns="columnsActivities" tableName="Activities" /> | ||
<template> | ||
<LayoutAccount> | ||
<div class="p-4"> | ||
<h2 class="text-2xl font-bold mb-4">User Activities</h2> | ||
<div v-if="loading" class="text-center py-4"> | ||
<div class="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-gray-900"></div> | ||
<p class="mt-2">Loading activities...</p> | ||
</div> | ||
<div v-else-if="error" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded" role="alert"> | ||
<p>{{ error }}</p> | ||
</div> | ||
<div v-else-if="activities.length === 0" class="text-center py-4"> | ||
<p>No activities found.</p> | ||
</div> | ||
<div v-else class="overflow-x-auto"> | ||
<table class="min-w-full bg-white border border-gray-300"> | ||
<thead> | ||
<tr> | ||
<th v-for="column in columns" :key="column.key" | ||
class="px-6 py-3 bg-gray-100 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"> | ||
{{ column.title }} | ||
</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr v-for="activity in activities" :key="activity.id" class="border-b border-gray-200"> | ||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">{{ activity.id }} | ||
</td> | ||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">{{ activity.action | ||
}}</td> | ||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">{{ | ||
activity.ip_address }}</td> | ||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">{{ | ||
formatDate(activity.date) }}</td> | ||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">{{ activity.deleted | ||
}}</td> | ||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">{{ activity.locked | ||
}}</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</div> | ||
</div> | ||
</div> | ||
</LayoutAccount> | ||
</template> | ||
|
||
<style scoped> | ||
/* Hide scrollbar for Chrome, Safari and Opera */ | ||
.overflow-x-auto::-webkit-scrollbar { | ||
display: none; | ||
} | ||
/* Hide scrollbar for IE, Edge and Firefox */ | ||
.overflow-x-auto { | ||
-ms-overflow-style: none; | ||
/* IE and Edge */ | ||
scrollbar-width: none; | ||
/* Firefox */ | ||
} | ||
</style> | ||
</style> |
49 changes: 49 additions & 0 deletions
49
frontend/src/components/client/Dashboard/Account/ActivityTable.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<script setup lang="ts"> | ||
import { format } from 'date-fns' | ||
interface Activity { | ||
id: number | ||
user: string | ||
action: string | ||
ip_address: string | ||
deleted: string | ||
locked: string | ||
date: string | ||
} | ||
defineProps<{ | ||
activities: Activity[] | ||
}>() | ||
</script> | ||
|
||
<template> | ||
<div class="overflow-x-auto bg-gray-900 rounded-lg shadow"> | ||
<table class="min-w-full divide-y divide-gray-800"> | ||
<thead class="bg-gray-800"> | ||
<tr> | ||
<th scope="col" | ||
class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider"> | ||
Action | ||
</th> | ||
<th scope="col" | ||
class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider"> | ||
IP Address | ||
</th> | ||
<th scope="col" | ||
class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider"> | ||
Date | ||
</th> | ||
</tr> | ||
</thead> | ||
<tbody class="bg-gray-900 divide-y divide-gray-800"> | ||
<tr v-for="activity in activities" :key="activity.id" class="hover:bg-gray-800 transition-colors"> | ||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-300">{{ activity.action }}</td> | ||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-300">{{ activity.ip_address }}</td> | ||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-300"> | ||
{{ format(new Date(activity.date), 'MMM d, yyyy HH:mm:ss') }} | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
class Activities { | ||
/** | ||
* Get the activities for the current session | ||
* | ||
* @returns The response from the server | ||
*/ | ||
public static async get() { | ||
const response = await fetch('/api/user/session/activities', { | ||
method: 'GET', | ||
}); | ||
const data = await response.json(); | ||
return data.activities; | ||
} | ||
} | ||
|
||
export default Activities; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters