Merge pull request '69-Navbar-user' (#106) from 69-Navbar-user into main
All checks were successful
Continuous Integration / Update Development (push) Successful in 2m27s
All checks were successful
Continuous Integration / Update Development (push) Successful in 2m27s
Reviewed-on: #106
This commit was merged in pull request #106.
This commit is contained in:
@@ -5,9 +5,9 @@ import { Request, Response } from 'express';
|
|||||||
import pool from '../db';
|
import pool from '../db';
|
||||||
import { requireLogin, requireMemberState, requireRole } from '../middleware/auth';
|
import { requireLogin, requireMemberState, requireRole } from '../middleware/auth';
|
||||||
import { getUserActiveLOA } from '../services/loaService';
|
import { getUserActiveLOA } from '../services/loaService';
|
||||||
import { getAllMembersLite, getMemberSettings, getMembersFull, getMembersLite, getUserData, setUserSettings } from '../services/memberService';
|
import { getAllMembersLite, getMemberSettings, getMembersFull, getMembersLite, getUserData, getUserState, setUserSettings } from '../services/memberService';
|
||||||
import { getUserRoles } from '../services/rolesService';
|
import { getUserRoles } from '../services/rolesService';
|
||||||
import { memberSettings, MemberState } from '@app/shared/types/member';
|
import { memberSettings, MemberState, myData } from '@app/shared/types/member';
|
||||||
|
|
||||||
//get all users
|
//get all users
|
||||||
router.get('/', [requireLogin, requireMemberState(MemberState.Member)], async (req, res) => {
|
router.get('/', [requireLogin, requireMemberState(MemberState.Member)], async (req, res) => {
|
||||||
@@ -37,12 +37,12 @@ router.get('/me', [requireLogin], async (req, res) => {
|
|||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { id, name, state } = await getUserData(req.user.id);
|
const memData = await getUserData(req.user.id);
|
||||||
const LOAData = await getUserActiveLOA(req.user.id);
|
const LOAData = await getUserActiveLOA(req.user.id);
|
||||||
|
const memState = await getUserState(req.user.id);
|
||||||
const roleData = await getUserRoles(req.user.id);
|
const roleData = await getUserRoles(req.user.id);
|
||||||
|
|
||||||
const userDataFull = { id, name, state, LOAData, roleData };
|
const userDataFull: myData = { member: memData, LOAs: LOAData, roles: roleData, state: memState };
|
||||||
res.status(200).json(userDataFull);
|
res.status(200).json(userDataFull);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching user data:', error);
|
console.error('Error fetching user data:', error);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import pool from "../db";
|
import pool from "../db";
|
||||||
import { Member, MemberLight, memberSettings, MemberState } from '@app/shared/types/member'
|
import { Member, MemberLight, memberSettings, MemberState } from '@app/shared/types/member'
|
||||||
|
|
||||||
export async function getUserData(userID: number) {
|
export async function getUserData(userID: number): Promise<Member> {
|
||||||
const sql = `SELECT * FROM members WHERE id = ?`;
|
const sql = `SELECT * FROM view_member_rank_unit_status_latest WHERE member_id = ?`;
|
||||||
const res = await pool.query(sql, [userID]);
|
const res: Member = await pool.query(sql, [userID]);
|
||||||
return res[0] ?? null;
|
return res[0] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { LOARequest } from "./loa";
|
||||||
|
import { Role } from "./roles";
|
||||||
|
|
||||||
export interface memberSettings {
|
export interface memberSettings {
|
||||||
displayName: string;
|
displayName: string;
|
||||||
}
|
}
|
||||||
@@ -30,3 +33,10 @@ export interface MemberLight {
|
|||||||
username: string
|
username: string
|
||||||
color: string
|
color: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface myData {
|
||||||
|
member: Member;
|
||||||
|
LOAs: LOARequest[];
|
||||||
|
roles: Role[];
|
||||||
|
state: MemberState;
|
||||||
|
}
|
||||||
@@ -179,7 +179,9 @@ function blurAfter() {
|
|||||||
<div>
|
<div>
|
||||||
<DropdownMenu v-if="userStore.isLoggedIn">
|
<DropdownMenu v-if="userStore.isLoggedIn">
|
||||||
<DropdownMenuTrigger class="cursor-pointer">
|
<DropdownMenuTrigger class="cursor-pointer">
|
||||||
<p>{{ userStore.user.name }}</p>
|
<Button variant="ghost" class="px-4">
|
||||||
|
{{ userStore.displayName }}
|
||||||
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
<DropdownMenuItem @click="$router.push('/profile')">My Profile</DropdownMenuItem>
|
<DropdownMenuItem @click="$router.push('/profile')">My Profile</DropdownMenuItem>
|
||||||
|
|||||||
@@ -105,7 +105,11 @@ onMounted(async () => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
members.value = await getMembers();
|
if (props.adminMode) {
|
||||||
|
members.value = await getMembers();
|
||||||
|
} else {
|
||||||
|
members.value.push(props.member);
|
||||||
|
}
|
||||||
loaTypes.value = await getLoaTypes();
|
loaTypes.value = await getLoaTypes();
|
||||||
resetForm({ values: { member_id: currentMember.value?.member_id } });
|
resetForm({ values: { member_id: currentMember.value?.member_id } });
|
||||||
});
|
});
|
||||||
@@ -153,7 +157,7 @@ const maxEndDate = computed(() => {
|
|||||||
<ComboboxInput placeholder="Search members..." class="w-full pl-3"
|
<ComboboxInput placeholder="Search members..." class="w-full pl-3"
|
||||||
:display-value="(id) => {
|
:display-value="(id) => {
|
||||||
const m = members.find(mem => mem.member_id === id)
|
const m = members.find(mem => mem.member_id === id)
|
||||||
return m ? m.member_name : ''
|
return m ? m.displayName || m.member_name : ''
|
||||||
}" />
|
}" />
|
||||||
</ComboboxAnchor>
|
</ComboboxAnchor>
|
||||||
<ComboboxList class="*:w-64">
|
<ComboboxList class="*:w-64">
|
||||||
@@ -162,7 +166,7 @@ const maxEndDate = computed(() => {
|
|||||||
<template v-for="member in members" :key="member.member_id">
|
<template v-for="member in members" :key="member.member_id">
|
||||||
<ComboboxItem :value="member.member_id"
|
<ComboboxItem :value="member.member_id"
|
||||||
class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
|
class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
|
||||||
{{ member.member_name }}
|
{{ member.displayName || member.member_name }}
|
||||||
<ComboboxItemIndicator
|
<ComboboxItemIndicator
|
||||||
class="absolute left-2 inline-flex items-center">
|
class="absolute left-2 inline-flex items-center">
|
||||||
<Check class="h-4 w-4" />
|
<Check class="h-4 w-4" />
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ export function useAuth() {
|
|||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
// Account status control
|
// Account status control
|
||||||
const accountStatus = computed(() => userStore.state);
|
const accountStatus = computed(() => userStore.user?.state);
|
||||||
|
|
||||||
// RBAC
|
// RBAC
|
||||||
const roles = computed<string[]>(() => {
|
const roles = computed<string[]>(() => {
|
||||||
return userStore.user?.roleData?.map((r: Role) => r.name) ?? [];
|
return userStore.user?.roles?.map((r: Role) => r.name) ?? [];
|
||||||
});
|
});
|
||||||
|
|
||||||
function isDev() {
|
function isDev() {
|
||||||
|
|||||||
@@ -1,20 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LoaForm from '@/components/loa/loaForm.vue';
|
import LoaForm from '@/components/loa/loaForm.vue';
|
||||||
import { useUserStore } from '@/stores/user';
|
import { useUserStore } from '@/stores/user';
|
||||||
import { Member } from '@/api/member';
|
import { Member } from '@shared/types/member';
|
||||||
import LoaList from '@/components/loa/loaList.vue';
|
import LoaList from '@/components/loa/loaList.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const user = userStore.user;
|
|
||||||
const memberFull: Member = {
|
|
||||||
member_id: user.id,
|
|
||||||
member_name: user.name,
|
|
||||||
rank: null,
|
|
||||||
rank_date: null,
|
|
||||||
status: null,
|
|
||||||
status_date: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const mode = ref<'submit' | 'view'>('submit')
|
const mode = ref<'submit' | 'view'>('submit')
|
||||||
</script>
|
</script>
|
||||||
@@ -32,7 +23,7 @@ const mode = ref<'submit' | 'view'>('submit')
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<LoaForm v-if="mode === 'submit'" :member="memberFull"></LoaForm>
|
<LoaForm v-if="mode === 'submit'" :member="userStore.user.member"></LoaForm>
|
||||||
<LoaList v-if="mode === 'view'" :admin-mode="false"></LoaList>
|
<LoaList v-if="mode === 'view'" :admin-mode="false"></LoaList>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,15 +1,18 @@
|
|||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import { myData } from '@shared/types/member'
|
||||||
|
|
||||||
|
|
||||||
const POLL_INTERVAL = 10_000
|
const POLL_INTERVAL = 10_000
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', () => {
|
export const useUserStore = defineStore('user', () => {
|
||||||
const user = ref(null)
|
const user = ref<myData>(null)
|
||||||
const roles = computed(() => new Set(user.value?.roleData?.map(r => r.name) ?? []));
|
const roles = computed(() => new Set(user.value?.roles?.map(r => r.name) ?? []));
|
||||||
const loaded = ref(false);
|
const loaded = ref(false);
|
||||||
const state = computed<string | undefined>(() => user.value?.state || undefined);
|
const state = computed<string | undefined>(() => user.value?.state || undefined);
|
||||||
const isLoggedIn = computed(() => user.value !== null)
|
const isLoggedIn = computed(() => user.value !== null)
|
||||||
|
const displayName = computed(() => user.value?.member.displayName || user.value?.member.member_name)
|
||||||
|
|
||||||
async function loadUser() {
|
async function loadUser() {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
@@ -19,7 +22,6 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
console.log(data);
|
|
||||||
user.value = data;
|
user.value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +42,6 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
watch(user, (newUser) => {
|
watch(user, (newUser) => {
|
||||||
if (!newUser) return
|
if (!newUser) return
|
||||||
console.log(newUser);
|
|
||||||
|
|
||||||
const currentRoute = route.meta
|
const currentRoute = route.meta
|
||||||
|
|
||||||
@@ -88,5 +89,5 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return { user, isLoggedIn, roles, loadUser, loaded, hasAnyRole, hasRole, state }
|
return { user, displayName, isLoggedIn, roles, loadUser, loaded, hasAnyRole, hasRole, state }
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user