import { defineStore } from 'pinia'; import { ref, computed } from 'vue'; import Client, { Local, admin as AdminNS, auth as AuthNS, profiles as ProfilesNS } from '@/encore/client'; import { useProfilesStore } from '@/stores/profiles-store'; export type Profile = AdminNS.Profile; export type ProfileParams = AdminNS.ProfileParams; export type RegisterParams = AdminNS.RegisterParams; export type PersonalData = AdminNS.PersonalData; export type PersonalDataParams = AdminNS.PersonalDataParams; export type UpdateProfilePasswordParams = AdminNS.UpdateProfilePasswordParams; export type RoleOption = AuthNS.RoleOption; export type StatusOption = ProfilesNS.StatusOption; export const useAdminStore = defineStore('admin', () => { const profiles = ref([]); const roles = ref([]); const statuses = ref([]); const loading = ref(false); const error = ref(null); const profilesStore = useProfilesStore(); const client = new Client(Local, { auth: () => (profilesStore.token ? { Authorization: `Bearer ${profilesStore.token}` } : undefined), }); async function withLoading(fn: () => Promise): Promise { loading.value = true; error.value = null; try { return await fn(); } catch (err) { error.value = err instanceof Error ? err.message : String(err); throw err; } finally { loading.value = false; } } /** Fetches all profiles into `profiles`. Requires the caller to be logged in as an admin. */ async function listProfiles(): Promise { return withLoading(async () => { const res = await client.admin.ListProfiles(); profiles.value = res.profiles; return res.profiles; }); } /** Creates a new user profile with credentials. Requires the caller to be logged in as an admin. */ async function insertProfile(params: RegisterParams): Promise { return withLoading(async () => { const res = await client.admin.InsertProfile(params); profiles.value.push(res); return res; }); } /** Fetches the valid roles and profile statuses into `roles` and `statuses`. */ async function fetchSystemOptions(): Promise { return withLoading(async () => { const res = await client.admin.GetSystemOptions(); roles.value = res.roles; statuses.value = res.statuses; }); } /** Statuses that an admin can manually set on a profile. */ const updatableStatuses = computed(() => statuses.value.filter((s) => s.updatable)); function replaceProfile(updated: Profile) { const idx = profiles.value.findIndex((p) => p.user_id === updated.user_id); if (idx !== -1) { profiles.value[idx] = updated; } } /** Updates any user's profile. Requires the caller to be logged in as an admin. */ async function updateProfile(userID: string, params: ProfileParams): Promise { return withLoading(async () => { const res = await client.admin.UpdateProfile(userID, params); replaceProfile(res); return res; }); } /** Updates the role of any user's profile. */ async function updateProfileRole(userID: string, role: string): Promise { return withLoading(async () => { const res = await client.admin.UpdateProfileRole(userID, { role }); replaceProfile(res); return res; }); } /** Updates the status of any user's profile. */ async function updateProfileStatus(userID: string, status: ProfilesNS.Status): Promise { return withLoading(async () => { const res = await client.admin.UpdateProfileStatus(userID, { status }); replaceProfile(res); return res; }); } /** Updates the password of any user's profile. */ async function updateProfilePassword(userID: string, params: UpdateProfilePasswordParams): Promise { return withLoading(async () => { await client.admin.UpdateProfilePassword(userID, params); }); } /** Fetches the personal data of any user. Requires the caller to be logged in as an admin. */ async function getPersonalData(userID: string): Promise { return withLoading(async () => { return await client.admin.GetPersonalData(userID); }); } /** Creates or replaces the personal data of any user. */ async function upsertPersonalData(userID: string, params: PersonalDataParams): Promise { return withLoading(async () => { return await client.admin.UpsertPersonalData(userID, params); }); } /** Uploads an avatar image and returns its public URL. */ async function uploadAvatar(image: Blob): Promise { return withLoading(async () => { const resp = await client.profiles.UploadAvatar('POST', image); if (!resp.ok) { throw new Error(`avatar upload failed (${resp.status})`); } const data = (await resp.json()) as { url: string }; return data.url; }); } return { // state profiles, roles, statuses, loading, error, // getters updatableStatuses, // actions listProfiles, fetchSystemOptions, insertProfile, updateProfile, updateProfileRole, updateProfileStatus, updateProfilePassword, getPersonalData, upsertPersonalData, uploadAvatar, }; });