update snapthots + admin panel users

This commit is contained in:
Emily
2025-03-10 15:54:00 +01:00
parent 942d074f99
commit 45e9a9c6a7
7 changed files with 122 additions and 50 deletions

View File

@@ -2,14 +2,34 @@
import { useSelectMenuStyle } from '~/composables/ui/useSelectMenuStyle';
import type { TAdminUser } from '~/server/api/admin/users';
import { sub, format, isSameDay, type Duration, startOfDay, endOfDay } from 'date-fns'
const filterText = ref<string>('');
watch(filterText,()=>{
watch(filterText, () => {
page.value = 1;
})
function isRangeSelected(duration: Duration) {
return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date())
}
function selectRange(duration: Duration) {
selected.value = { start: sub(new Date(), duration), end: new Date() }
}
const ranges = [
{ label: 'Last 7 days', duration: { days: 7 } },
{ label: 'Last 14 days', duration: { days: 14 } },
{ label: 'Last 30 days', duration: { days: 30 } },
{ label: 'Last 3 months', duration: { months: 3 } },
{ label: 'Last 6 months', duration: { months: 6 } },
{ label: 'Last year', duration: { years: 1 } }
]
const selected = ref<{ start: Date, end: Date }>({ start: sub(new Date(), { days: 14 }), end: new Date() })
const filter = computed(() => {
return JSON.stringify({
$or: [
@@ -39,7 +59,7 @@ const limitList = [
const limit = ref<number>(20);
const { data: usersInfo, pending: pendingUsers } = await useFetch<{ count: number, users: TAdminUser[] }>(
() => `/api/admin/users?page=${page.value - 1}&limit=${limit.value}&sortQuery=${order.value}&filterQuery=${filter.value}`,
() => `/api/admin/users?page=${page.value - 1}&limit=${limit.value}&sortQuery=${order.value}&filterQuery=${filter.value}&filterFrom=${selected.value.start.toISOString()}&filterTo=${selected.value.end.toISOString()}`,
signHeaders()
);
@@ -51,44 +71,71 @@ const { uiMenu } = useSelectMenuStyle();
<div class="mt-6 h-full">
<div class="flex items-center gap-10 px-10">
<div class="flex flex-col items-center gap-6">
<div class="flex gap-2 items-center">
<div>Order:</div>
<USelectMenu :uiMenu="uiMenu" class="w-[12rem]" placeholder="Order" :options="ordersList"
value-attribute="id" option-attribute="label" v-model="order">
</USelectMenu>
</div>
<div class="flex items-center gap-10 px-10">
<div class="flex gap-2 items-center">
<div>Order:</div>
<USelectMenu :uiMenu="uiMenu" class="w-[12rem]" placeholder="Order" :options="ordersList"
value-attribute="id" option-attribute="label" v-model="order">
</USelectMenu>
</div>
<div class="flex gap-2 items-center">
<div>Limit:</div>
<USelectMenu :uiMenu="uiMenu" class="w-[12rem]" placeholder="Limit" :options="limitList"
value-attribute="id" option-attribute="label" v-model="limit">
</USelectMenu>
</div>
<div class="flex gap-2 items-center">
<div>Limit:</div>
<USelectMenu :uiMenu="uiMenu" class="w-[12rem]" placeholder="Limit" :options="limitList"
value-attribute="id" option-attribute="label" v-model="limit">
</USelectMenu>
</div>
<div class="flex gap-2 items-center">
<LyxUiInput placeholder="Search user" class="px-2 py-1" v-model="filterText"></LyxUiInput>
</div>
<div class="flex gap-2 items-center">
<div>Page {{ page }} </div>
<div>
{{ Math.min(limit, usersInfo?.count || 0) }}
of
{{ usersInfo?.count || 0 }}
<div class="flex gap-2 items-center">
<LyxUiInput placeholder="Search user" class="px-2 py-1" v-model="filterText"></LyxUiInput>
</div>
</div>
<div>
<UPagination v-model="page" :page-count="limit" :total="usersInfo?.count || 0" />
<div class="flex items-centet gap-10">
<div class="flex gap-2 items-center">
<div>Page {{ page }} </div>
<div>
{{ Math.min(limit, usersInfo?.count || 0) }}
of
{{ usersInfo?.count || 0 }}
</div>
</div>
<div>
<UPagination v-model="page" :page-count="limit" :total="usersInfo?.count || 0" />
</div>
<UPopover class="w-[20rem]" :popper="{ placement: 'bottom' }">
<UButton class="w-full" color="primary" variant="solid">
<div class="flex items-center justify-center w-full gap-2">
<i class="i-heroicons-calendar-days-20-solid"></i>
{{ selected.start.toLocaleDateString() }} - {{ selected.end.toLocaleDateString() }}
</div>
</UButton>
<template #panel="{ close }">
<div class="flex items-center sm:divide-x divide-gray-200 dark:divide-gray-800">
<div class="hidden sm:flex flex-col py-4">
<UButton v-for="(range, index) in ranges" :key="index" :label="range.label" color="gray"
variant="ghost" class="rounded-none px-6"
:class="[isRangeSelected(range.duration) ? 'bg-gray-100 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50']"
truncate @click="selectRange(range.duration)" />
</div>
<DatePicker v-model="selected" @close="close" />
</div>
</template>
</UPopover>
</div>
</div>
<div
class="cursor-default flex justify-center flex-wrap gap-6 mb-[4rem] mt-4 overflow-auto h-full pt-6 pb-[8rem]">

View File

@@ -64,17 +64,17 @@ async function declineInvite(project_id: string) {
}">
<div class="h-full flex flex-col gap-8 p-6">
<div class="flex flex-col gap-2" v-for="invite of invites">
<div class="flex flex-col gap-6" v-for="invite of invites">
<div class="dark:text-lyx-text text-lyx-lightmode-text">
You are invited to join
<span class="font-semibold">{{ invite.project_name }}</span>.
Do you accept this invitation?
Do you accept?
</div>
<div class="flex gap-4">
<div class="flex gap-4 w-full justify-end">
<LyxUiButton @click="declineInvite(invite.project_id)" type="secondary"> Decline </LyxUiButton>
<LyxUiButton @click="acceptInvite(invite.project_id)" type="primary"> Accept </LyxUiButton>
<LyxUiButton @click="declineInvite(invite.project_id)" type="danger"> Decline </LyxUiButton>
</div>
</div>

View File

@@ -46,9 +46,17 @@ async function save(member_id: string) {
}">
<div class="p-8">
<div v-if="member" class="manage flex flex-col gap-4">
<div class="flex flex-col gap-1">
<div class="poppins text-[1.1rem]"> Manage permissions </div>
<div class="poppins text-[.9rem] dark:text-lyx-text-dark"> Choose what this member can do on this project. </div>
</div>
<LyxUiSeparator></LyxUiSeparator>
<div class="flex flex-col gap-1">
<div>
<div class="mb-1"> Allowed domains </div>
<div class="mb-1"> Select what domain is allowed to see: </div>
<div class="mb-1">
<USelectMenu v-model="member.permission.domains" :options="domainList" multiple
value-attribute="_id">
@@ -89,7 +97,7 @@ async function save(member_id: string) {
</div>
<div class="flex items-center gap-2">
<UCheckbox v-model="member.permission.ai"></UCheckbox>
<div> Allow AI page </div>
<div> Allow to use AI data analyst </div>
</div>
</div>
</div>
@@ -98,10 +106,10 @@ async function save(member_id: string) {
<div class="flex gap-2 justify-end mt-8">
<LyxUiButton v-if="member?.permission" @click="save(member._id.toString())" type="primary">
<LyxUiButton class="!w-[6rem] text-center" type="secondary" @click="emit('cancel')"> Cancel </LyxUiButton>
<LyxUiButton class="!w-[6rem] text-center" v-if="member?.permission" @click="save(member._id.toString())" type="primary">
Save
</LyxUiButton>
<LyxUiButton type="secondary" @click="emit('cancel')"> Cancel </LyxUiButton>
</div>
</div>