Refactored org modal logic

This commit is contained in:
2026-10-04 18:21:48 +02:00
parent c9deba0427
commit 236f6f0f9d
@@ -551,7 +551,7 @@ export const GovernancePage: React.FC = () => {
const openCreateOrg = () => {
setEditingOrg(null);
const defaultUserId = usersDirectory[0]?.id || sub || currentUserId;
const defaultUserId = usersDirectory[0]?.id || sub || currentUserId || '';
const defaultUser = usersDirectory.find((u) => u.id === defaultUserId);
orgForm.reset({
name: '',
@@ -565,70 +565,58 @@ export const GovernancePage: React.FC = () => {
setIsOrgModalOpen(true);
};
const openEditOrg = async (org: Organisation) => {
const openEditOrg = (org: Organisation) => {
setEditingOrg(org);
setIsOrgModalOpen(true);
// 1. Fetch fresh organisation details from API
let currentOrg = org;
try {
const fresh = await getOrganisation(org.id);
if (fresh) {
currentOrg = fresh;
}
} catch {
// fallback to passed org
}
// 2. Resolve linked user ID from organisation model
// 1. Resolve target linked user ID synchronously from the organisation model
const targetUserId =
currentOrg.userId ||
(currentOrg as any).UserId ||
(currentOrg as any).organisationUser ||
(currentOrg as any).OrganisationUser ||
currentOrg.createdBy ||
org.userId ||
(org as any).UserId ||
(org as any).organisationUser ||
(org as any).OrganisationUser ||
org.createdBy ||
'';
// 3. Find user in directory or fetch user record to get cached user profile and idNumber
let matchedUser = usersDirectory.find(
(u) => u.id && String(u.id).toLowerCase() === String(targetUserId).toLowerCase()
);
// 2. Fast O(1) in-memory match from cached users directory
const matchedUser = targetUserId
? usersDirectory.find((u) => u.id && String(u.id).toLowerCase() === String(targetUserId).toLowerCase())
: null;
if (!matchedUser && targetUserId) {
try {
const fetchedUser = await getUser(targetUserId);
if (fetchedUser) {
matchedUser = fetchedUser;
}
} catch {
// user fetch failed
}
}
// 4. Ensure matched user is present in usersDirectory cache for dropdown rendering
if (matchedUser && !usersDirectory.some((u) => u.id === matchedUser!.id)) {
queryClient.setQueryData<User[]>(['users-directory'], (old = []) => [matchedUser!, ...old]);
}
// 5. Resolve idNumber from matched user profile or organisation
const resolvedIdNumber =
matchedUser?.idNumber ||
currentOrg.idNumber ||
(currentOrg as any).IdNumber ||
(org as any).idNumber ||
'';
const selectedUserId = matchedUser?.id || targetUserId || usersDirectory[0]?.id || currentUserId;
// 3. Resolve idNumber: prefer matchedUser's idNumber, or org's idNumber if any, otherwise blank ''
const resolvedIdNumber = matchedUser?.idNumber || org.idNumber || (org as any).IdNumber || '';
const selectedUserId = matchedUser?.id || targetUserId || '';
// 4. Perform assignment immediately to form state
orgForm.reset({
name: currentOrg.name || '',
registrationNo: currentOrg.registrationNo || '',
email: currentOrg.email || '',
name: org.name || '',
registrationNo: org.registrationNo || '',
email: org.email || '',
idNumber: resolvedIdNumber,
organisationUser: selectedUserId,
type: currentOrg.type || OrganisationType.Enterprise,
status: currentOrg.status ?? ActivityStatus.Active,
type: org.type || OrganisationType.Enterprise,
status: org.status ?? ActivityStatus.Active,
});
// 5. Instantly open modal with fully populated data (no lag, no progressive pop-in)
setIsOrgModalOpen(true);
// 6. Non-blocking background sync if target user wasn't in cache or org has missing data
if (targetUserId && !matchedUser) {
getUser(targetUserId).then((fetchedUser) => {
if (fetchedUser) {
queryClient.setQueryData<User[]>(['users-directory'], (old = []) => {
if (old.some((u) => u.id === fetchedUser.id)) return old;
return [fetchedUser, ...old];
});
if (fetchedUser.idNumber && !orgForm.getValues('idNumber')) {
orgForm.setValue('idNumber', fetchedUser.idNumber, { shouldValidate: true });
}
if (!orgForm.getValues('organisationUser')) {
orgForm.setValue('organisationUser', fetchedUser.id, { shouldValidate: true });
}
}
}).catch(() => {});
}
};
const openCreatePortfolio = () => {
@@ -1499,23 +1487,16 @@ export const GovernancePage: React.FC = () => {
</div>
<select
{...orgForm.register('organisationUser', {
onChange: async (e) => {
onChange: (e) => {
const selectedId = e.target.value;
let selected = usersDirectory.find((u) => u.id === selectedId);
if (!selected && selectedId) {
try {
selected = await getUser(selectedId);
} catch {
// ignore
}
}
if (selected?.idNumber) {
orgForm.setValue('idNumber', selected.idNumber, { shouldValidate: true });
}
const selected = usersDirectory.find((u) => u.id === selectedId);
// Populate selected user's ID number or blank '' if deselected or missing
orgForm.setValue('idNumber', selected?.idNumber || '', { shouldValidate: true });
},
})}
className="w-full px-3 py-2 text-xs border border-slate-700/80 rounded-xl focus:outline-none focus:ring-1 focus:ring-blue-500 bg-[#090d16] text-white font-medium"
>
<option value="">-- Select linked user account --</option>
{usersDirectory.map((u) => (
<option key={u.id} value={u.id}>
{u.email || u.id} {u.role ? `(${u.role})` : ''} {u.idNumber ? `• ID: ${u.idNumber}` : ''}