115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
// Ported from legacy henza_admin/src/store/users/index.js
|
|
import { defineStore } from 'pinia';
|
|
import api from '../api/client';
|
|
|
|
/**
|
|
* Ported VERBATIM in behaviour from legacy store/users/index.js:3-9.
|
|
*
|
|
* getParents(['a','b','c']) -> ['a.b', 'a']
|
|
*/
|
|
function getParents(keys: string[]): string[] {
|
|
const work = [...keys];
|
|
const parents: string[] = [];
|
|
while (work.length > 1) {
|
|
work.pop();
|
|
parents.push(work.join('.'));
|
|
}
|
|
return parents;
|
|
}
|
|
|
|
/**
|
|
* Ported from legacy store/users/index.js:10-22.
|
|
*
|
|
* Granting "persons.list.client.omde" implicitly grants "persons.list.client",
|
|
* "persons.list" and "persons", which is what keeps parent menu nodes visible.
|
|
*
|
|
* The legacy version assigned to a module-scoped `let rid` and relied on that
|
|
* outer variable inside the .map() callback. This version is pure — identical
|
|
* output, but no state leaking between calls (legacy's `rid` survived logout).
|
|
*
|
|
* NOTE it only walks UP; a rid never implies its children. That is why a user
|
|
* granted "wallet" still cannot see the nav item guarded by "wallet.list" —
|
|
* a legacy bug, preserved deliberately. See docs/ADMIN-PORT-PLAN.md.
|
|
*/
|
|
export function checkParent(values: string[]): string[] {
|
|
let rid: string[] = [...values];
|
|
values.forEach((x) => {
|
|
const keys = x.split('.');
|
|
if (keys.length > 1) {
|
|
rid = [...new Set([...rid, ...getParents(keys)])];
|
|
}
|
|
});
|
|
return rid;
|
|
}
|
|
|
|
export interface UserInfo {
|
|
id?: string;
|
|
name?: string;
|
|
fullName?: string;
|
|
/**
|
|
* Legacy split names into fname/lname. The schema stores one fullName, but the
|
|
* API returns both keys so ported templates binding either keep working.
|
|
*/
|
|
fname?: string;
|
|
lname?: string;
|
|
mobile?: string;
|
|
role?: string;
|
|
ut?: number | null;
|
|
branch_id?: string | null;
|
|
user_type?: { id: number; title: string } | null;
|
|
}
|
|
|
|
export const useUsersStore = defineStore('users', {
|
|
state: () => ({
|
|
// legacy: cityFilters — id -> title map used by table filters
|
|
cityFilters: {} as Record<string | number, string>,
|
|
userInfo: undefined as UserInfo | undefined,
|
|
// undefined = "not fetched yet" (distinct from [] = "fetched, has none").
|
|
// The router guard relies on that distinction, as legacy's did.
|
|
roles: undefined as string[] | undefined,
|
|
}),
|
|
getters: {
|
|
/**
|
|
* Port of the global `Vue.prototype.$hasPermission` from legacy main.js.
|
|
* Returns undefined when roles have not loaded — legacy did the same, which
|
|
* renders as falsy in v-if.
|
|
*/
|
|
hasPermission: (state) => (permissionId: string) => {
|
|
const roles = state.roles;
|
|
if (roles) {
|
|
return roles.includes(permissionId);
|
|
}
|
|
return undefined;
|
|
},
|
|
},
|
|
actions: {
|
|
// legacy mutation setCities: builds an id -> title lookup
|
|
setCities(payload: { id: string | number; title: string }[]) {
|
|
payload.forEach((x) => {
|
|
this.cityFilters[x.id] = x.title;
|
|
});
|
|
},
|
|
async getCities() {
|
|
try {
|
|
const res = await api.post('cities/list');
|
|
this.setCities(res.data.rows);
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
},
|
|
setUserInfo(payload: UserInfo) {
|
|
this.userInfo = payload;
|
|
},
|
|
deleteUserInfo() {
|
|
this.userInfo = {};
|
|
},
|
|
/** legacy action getRoles: commits checkParent(roles), never the raw list. */
|
|
getRoles(roles: string[]) {
|
|
this.roles = checkParent(roles);
|
|
},
|
|
deleteRoles() {
|
|
this.roles = undefined;
|
|
},
|
|
},
|
|
});
|