Merge pull request 'Refactored org modal logic' (#135) from finishline into main
Reviewed-on: #135
This commit was merged in pull request #135.
This commit is contained in:
@@ -551,7 +551,7 @@ export const GovernancePage: React.FC = () => {
|
|||||||
|
|
||||||
const openCreateOrg = () => {
|
const openCreateOrg = () => {
|
||||||
setEditingOrg(null);
|
setEditingOrg(null);
|
||||||
const defaultUserId = usersDirectory[0]?.id || sub || currentUserId;
|
const defaultUserId = usersDirectory[0]?.id || sub || currentUserId || '';
|
||||||
const defaultUser = usersDirectory.find((u) => u.id === defaultUserId);
|
const defaultUser = usersDirectory.find((u) => u.id === defaultUserId);
|
||||||
orgForm.reset({
|
orgForm.reset({
|
||||||
name: '',
|
name: '',
|
||||||
@@ -565,70 +565,58 @@ export const GovernancePage: React.FC = () => {
|
|||||||
setIsOrgModalOpen(true);
|
setIsOrgModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openEditOrg = async (org: Organisation) => {
|
const openEditOrg = (org: Organisation) => {
|
||||||
setEditingOrg(org);
|
setEditingOrg(org);
|
||||||
setIsOrgModalOpen(true);
|
|
||||||
|
|
||||||
// 1. Fetch fresh organisation details from API
|
// 1. Resolve target linked user ID synchronously from the organisation model
|
||||||
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
|
|
||||||
const targetUserId =
|
const targetUserId =
|
||||||
currentOrg.userId ||
|
org.userId ||
|
||||||
(currentOrg as any).UserId ||
|
(org as any).UserId ||
|
||||||
(currentOrg as any).organisationUser ||
|
(org as any).organisationUser ||
|
||||||
(currentOrg as any).OrganisationUser ||
|
(org as any).OrganisationUser ||
|
||||||
currentOrg.createdBy ||
|
org.createdBy ||
|
||||||
'';
|
'';
|
||||||
|
|
||||||
// 3. Find user in directory or fetch user record to get cached user profile and idNumber
|
// 2. Fast O(1) in-memory match from cached users directory
|
||||||
let matchedUser = usersDirectory.find(
|
const matchedUser = targetUserId
|
||||||
(u) => u.id && String(u.id).toLowerCase() === String(targetUserId).toLowerCase()
|
? usersDirectory.find((u) => u.id && String(u.id).toLowerCase() === String(targetUserId).toLowerCase())
|
||||||
);
|
: null;
|
||||||
|
|
||||||
if (!matchedUser && targetUserId) {
|
// 3. Resolve idNumber: prefer matchedUser's idNumber, or org's idNumber if any, otherwise blank ''
|
||||||
try {
|
const resolvedIdNumber = matchedUser?.idNumber || org.idNumber || (org as any).IdNumber || '';
|
||||||
const fetchedUser = await getUser(targetUserId);
|
const selectedUserId = matchedUser?.id || 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;
|
|
||||||
|
|
||||||
|
// 4. Perform assignment immediately to form state
|
||||||
orgForm.reset({
|
orgForm.reset({
|
||||||
name: currentOrg.name || '',
|
name: org.name || '',
|
||||||
registrationNo: currentOrg.registrationNo || '',
|
registrationNo: org.registrationNo || '',
|
||||||
email: currentOrg.email || '',
|
email: org.email || '',
|
||||||
idNumber: resolvedIdNumber,
|
idNumber: resolvedIdNumber,
|
||||||
organisationUser: selectedUserId,
|
organisationUser: selectedUserId,
|
||||||
type: currentOrg.type || OrganisationType.Enterprise,
|
type: org.type || OrganisationType.Enterprise,
|
||||||
status: currentOrg.status ?? ActivityStatus.Active,
|
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 = () => {
|
const openCreatePortfolio = () => {
|
||||||
@@ -1499,23 +1487,16 @@ export const GovernancePage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<select
|
<select
|
||||||
{...orgForm.register('organisationUser', {
|
{...orgForm.register('organisationUser', {
|
||||||
onChange: async (e) => {
|
onChange: (e) => {
|
||||||
const selectedId = e.target.value;
|
const selectedId = e.target.value;
|
||||||
let selected = usersDirectory.find((u) => u.id === selectedId);
|
const selected = usersDirectory.find((u) => u.id === selectedId);
|
||||||
if (!selected && selectedId) {
|
// Populate selected user's ID number or blank '' if deselected or missing
|
||||||
try {
|
orgForm.setValue('idNumber', selected?.idNumber || '', { shouldValidate: true });
|
||||||
selected = await getUser(selectedId);
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selected?.idNumber) {
|
|
||||||
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"
|
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) => (
|
{usersDirectory.map((u) => (
|
||||||
<option key={u.id} value={u.id}>
|
<option key={u.id} value={u.id}>
|
||||||
{u.email || u.id} {u.role ? `(${u.role})` : ''} {u.idNumber ? `• ID: ${u.idNumber}` : ''}
|
{u.email || u.id} {u.role ? `(${u.role})` : ''} {u.idNumber ? `• ID: ${u.idNumber}` : ''}
|
||||||
|
|||||||
Reference in New Issue
Block a user