refactor: simplify profile lookup and navigation logic commit

This commit is contained in:
mengstabketemaw
2026-06-27 09:37:29 +03:00
parent 83dafbfd7c
commit 1a472a6db3
3 changed files with 30 additions and 59 deletions

View File

@@ -24,7 +24,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { useNavigate } from 'react-router-dom';
import { useApiMutation } from '@ema-platform/api';
import { notify } from '@ema-platform/ui';
import { authStorage, setUser, logout } from '@ema-platform/auth';
import { authStorage, setUser, logout, type AuthUser } from '@ema-platform/auth';
import { useAppDispatch, useAppSelector } from '../../../store/hooks';
import {
ProfileFormContent,
@@ -109,12 +109,6 @@ function StepIndicator({ active, completed }: { active: number; completed: numbe
);
}
function inferUserType(professionName: string): string {
const name = professionName.toLowerCase();
if (name.includes('seafarer')) return 'SEAFARER';
return 'EMPLOYEE';
}
export function ProfileSetupPage() {
const navigate = useNavigate();
const dispatch = useAppDispatch();
@@ -126,13 +120,10 @@ export function ProfileSetupPage() {
const [professionsLoading, setProfessionsLoading] = useState(true);
const [profileTrigger] = useApiMutation<{ id: string }>();
const [addressTrigger] = useApiMutation<unknown>();
const [meTrigger] = useApiMutation<{ id: string }>();
const [profileCheckTrigger] = useApiMutation<{ total: number; items: Array<{ id: string; user: { id: string }; isComplete: boolean }> }>();
const [meTrigger] = useApiMutation<AuthUser>();
const [fetchProfessions] = useApiMutation<{ count: number; items: Array<{ id: string; name: { en: string } }> }>();
const fetched = useRef(false);
const checkedExistingProfile = useRef(false);
useEffect(() => {
if (fetched.current) return;
fetched.current = true;
@@ -143,21 +134,6 @@ export function ProfileSetupPage() {
.finally(() => setProfessionsLoading(false));
}, [fetchProfessions]);
useEffect(() => {
if (!user || checkedExistingProfile.current) return;
checkedExistingProfile.current = true;
profileCheckTrigger({ url: `/profiles?q=${encodeURIComponent('i=user')}`, method: 'GET' })
.unwrap()
.then((data) => {
const existing = data.items?.find((p) => p.user?.id === user.id);
if (existing?.isComplete) {
authStorage.setProfileId(existing.id);
navigate('/dashboard', { replace: true });
}
})
.catch(() => {});
}, [user, navigate, profileCheckTrigger]);
const professionOptions = useMemo(
() => professions.map((p) => ({ value: p.id, label: p.name.en })),
[professions],
@@ -248,7 +224,7 @@ export function ProfileSetupPage() {
method: 'POST',
body: {
userId: user?.id,
type: inferUserType(selectedProfessionName),
type: 'SEAFARER',
professionId: pv.professionId,
firstName: pv.firstName,
middleName: pv.middleName,
@@ -259,12 +235,6 @@ export function ProfileSetupPage() {
maritalStatus: pv.maritalStatus,
},
}).unwrap();
await profileTrigger({
url: `/profiles/${profileResult.id}`,
method: 'PUT',
body: { isComplete: true },
}).unwrap();
authStorage.setProfileId(profileResult.id);
await addressTrigger({

View File

@@ -131,19 +131,16 @@ export function ProfilePage() {
const [loadedProfile, setLoadedProfile] = useState<ProfileValues | null>(null);
const [loadedAddress, setLoadedAddress] = useState<AddressValues | null>(null);
const [profileId, setProfileId] = useState<string | null>(null);
const [addressId, setAddressId] = useState<string | null>(null);
const [dataLoading, setDataLoading] = useState(true);
const profileId = authStorage.getProfileId();
useEffect(() => {
if (!profileId) {
setDataLoading(false);
return;
}
fetchProfile({ url: `/profiles/${profileId}?i=address,profession`, method: 'GET' })
if (!user) return;
fetchProfile({ url: `/profiles/by-user/${user.id}`, method: 'GET' })
.unwrap()
.then((data) => {
setProfileId(data.id);
setLoadedProfile({
professionId: data.professionId || data.profession?.id || '',
firstName: data.firstName || '',
@@ -181,7 +178,7 @@ export function ProfilePage() {
.catch(() => {
setDataLoading(false);
});
}, [profileId, fetchProfile]);
}, [user, fetchProfile]);
// Load the latest user from the server on mount
useEffect(() => {

View File

@@ -46,7 +46,7 @@ export function LoginPage() {
const [rememberMe, setRememberMe] = useState(true);
const [loginTrigger] = useApiMutation<LoginPayload>();
const [meTrigger] = useApiMutation<AuthUser>();
const [profileCheckTrigger] = useApiMutation<{ total: number; items: Array<{ id: string; user: { id: string }; isComplete: boolean }> }>();
const [profileCheckTrigger] = useApiMutation<{ id: string }>();
const {
register,
@@ -72,31 +72,35 @@ export function LoginPage() {
}).unwrap();
dispatch(setUser(me));
let hasProfile = false;
try {
const profiles = await profileCheckTrigger({
url: `/profiles?q=${encodeURIComponent('i=user')}`,
const profile = await profileCheckTrigger({
url: `/profiles/by-user/${me.id}`,
method: 'GET',
}).unwrap();
const userProfile = profiles.items?.find((p) => p.user?.id === me.id);
if (userProfile?.isComplete) {
authStorage.setProfileId(userProfile.id);
} else {
navigate('/profile-setup');
return;
}
authStorage.setProfileId(profile.id);
hasProfile = true;
} catch {
// profile not found — redirect to setup
}
if (!me.isPhoneNumberVerified) {
navigate('/otp-verify', {
state: {
email: me.email,
phoneNumber: me.phoneNumber,
needsProfile: !hasProfile,
},
});
return;
}
if (!hasProfile) {
navigate('/profile-setup');
return;
}
if (me.isPhoneNumberVerified) {
navigate(loginRedirectPath);
} else {
navigate('/otp-verify', {
state: { email: me.email, phoneNumber: me.phoneNumber },
});
}
navigate(loginRedirectPath);
} catch {
notify.error('Invalid email or password');
} finally {