feat: mejorar el componente de ayuda para proformas y ajustar pruebas de actualización
This commit is contained in:
parent
a37d6fc96b
commit
1a8d63373d
@ -10,6 +10,7 @@ import {
|
|||||||
Separator,
|
Separator,
|
||||||
} from "@repo/shadcn-ui/components";
|
} from "@repo/shadcn-ui/components";
|
||||||
import { AlertCircleIcon, CheckCircle2Icon, CircleDashedIcon, CircleHelpIcon } from "lucide-react";
|
import { AlertCircleIcon, CheckCircle2Icon, CircleDashedIcon, CircleHelpIcon } from "lucide-react";
|
||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
import { useTranslation } from "../../../../i18n";
|
import { useTranslation } from "../../../../i18n";
|
||||||
import type { ProformaIssuanceReadiness } from "../../../shared";
|
import type { ProformaIssuanceReadiness } from "../../../shared";
|
||||||
@ -23,7 +24,7 @@ interface ProformaUpdateHelpPopoverProps {
|
|||||||
onRetryReadiness?: () => void;
|
onRetryReadiness?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HelpTriggerProps {
|
interface HelpTriggerProps extends ComponentProps<typeof Button> {
|
||||||
ariaLabel: string;
|
ariaLabel: string;
|
||||||
pendingBlockersCount: number;
|
pendingBlockersCount: number;
|
||||||
}
|
}
|
||||||
@ -39,9 +40,16 @@ interface HelpReadinessSectionProps {
|
|||||||
translate: (key: string, params?: Record<string, string | number | null | undefined>) => string;
|
translate: (key: string, params?: Record<string, string | number | null | undefined>) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HelpTrigger = ({ ariaLabel, pendingBlockersCount }: HelpTriggerProps) => {
|
const HelpTrigger = ({ ariaLabel, className, pendingBlockersCount, ...props }: HelpTriggerProps) => {
|
||||||
return (
|
return (
|
||||||
<Button aria-label={ariaLabel} className="relative" size="icon" type="button" variant="outline">
|
<Button
|
||||||
|
{...props}
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
className={className ? `relative ${className}` : "relative"}
|
||||||
|
size="icon"
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
<CircleHelpIcon aria-hidden="true" className="size-4" />
|
<CircleHelpIcon aria-hidden="true" className="size-4" />
|
||||||
{pendingBlockersCount > 0 ? (
|
{pendingBlockersCount > 0 ? (
|
||||||
<Badge
|
<Badge
|
||||||
@ -190,9 +198,9 @@ export const ProformaUpdateHelpPopover = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger
|
||||||
<HelpTrigger ariaLabel={triggerAriaLabel} pendingBlockersCount={pendingBlockersCount} />
|
render={<HelpTrigger ariaLabel={triggerAriaLabel} pendingBlockersCount={pendingBlockersCount} />}
|
||||||
</PopoverTrigger>
|
/>
|
||||||
|
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
align="end"
|
align="end"
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const buildFormData = (value: Partial<ProformaUpdateForm> = {}): ProformaUpdateF
|
|||||||
...value,
|
...value,
|
||||||
}) as ProformaUpdateForm;
|
}) as ProformaUpdateForm;
|
||||||
|
|
||||||
test("excluye items vacíos no valorados al construir el PUT de update", () => {
|
test("mantiene los items vacíos y respeta su orden al construir el PUT de update", () => {
|
||||||
const formData = buildFormData({
|
const formData = buildFormData({
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
@ -66,7 +66,17 @@ test("excluye items vacíos no valorados al construir el PUT de update", () => {
|
|||||||
formData
|
formData
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(result.data.items?.length, 1);
|
assert.equal(result.data.items?.length, 2);
|
||||||
assert.equal(result.data.items?.[0]?.description, "Servicio");
|
assert.equal(result.data.items?.[0]?.description, "");
|
||||||
|
assert.equal(result.data.items?.[0]?.quantity, null);
|
||||||
|
assert.equal(result.data.items?.[0]?.unit_amount, null);
|
||||||
assert.equal(result.data.items?.[0]?.position, 0);
|
assert.equal(result.data.items?.[0]?.position, 0);
|
||||||
|
assert.equal(result.data.items?.[1]?.description, "Servicio");
|
||||||
|
assert.deepEqual(result.data.items?.[1]?.quantity, { value: "100", scale: "2" });
|
||||||
|
assert.deepEqual(result.data.items?.[1]?.unit_amount, {
|
||||||
|
value: "1000000",
|
||||||
|
scale: "4",
|
||||||
|
currency_code: "EUR",
|
||||||
|
});
|
||||||
|
assert.equal(result.data.items?.[1]?.position, 1);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -109,9 +109,7 @@ export const buildUpdateProformaByIdParams = (
|
|||||||
// Si se han tocado los detalles, se envían todos
|
// Si se han tocado los detalles, se envían todos
|
||||||
if (shouldReplaceItems(patch)) {
|
if (shouldReplaceItems(patch)) {
|
||||||
const context = buildProformaItemUpdateDTOContext(formData);
|
const context = buildProformaItemUpdateDTOContext(formData);
|
||||||
data.items = formData.items
|
data.items = formData.items.map((item, index) => toProformaItemUpdateDTO(item, index, context));
|
||||||
.filter(isValuedProformaItem)
|
|
||||||
.map((item, index) => toProformaItemUpdateDTO(item, index, context));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -146,10 +144,6 @@ const toProformaItemUpdateDTO = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const isValuedProformaItem = (item: ProformaItemUpdateForm): boolean => {
|
|
||||||
return item.quantity !== null && item.unitAmount !== null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildProformaItemUpdateDTOContext = (
|
const buildProformaItemUpdateDTOContext = (
|
||||||
formData: ProformaUpdateForm
|
formData: ProformaUpdateForm
|
||||||
): ProformaItemUpdateDTOContext => {
|
): ProformaItemUpdateDTOContext => {
|
||||||
|
|||||||
@ -1,404 +1,404 @@
|
|||||||
import { useDataSource } from "@erp/core/hooks";
|
import { useDataSource } from "@erp/core/hooks";
|
||||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
import type { LoginForm } from "../login/entities";
|
import type { LoginForm } from "../login/entities";
|
||||||
import {
|
import {
|
||||||
AvailableCompaniesResponseDTOSchema,
|
AvailableCompaniesResponseDTOSchema,
|
||||||
activeCompanyStorage,
|
activeCompanyStorage,
|
||||||
authTokenStorage,
|
authTokenStorage,
|
||||||
findAvailableCompanies,
|
findAvailableCompanies,
|
||||||
mapAvailableCompany,
|
mapAvailableCompany,
|
||||||
mapCurrentSessionToAuthSession,
|
mapCurrentSessionToAuthSession,
|
||||||
resolveAuthenticatedRedirectPath,
|
resolveAuthenticatedRedirectPath,
|
||||||
resolveCompanySession,
|
resolveCompanySession,
|
||||||
useLoginMutation,
|
useLoginMutation,
|
||||||
useLogoutMutation,
|
useLogoutMutation,
|
||||||
useRefreshSessionMutation,
|
useRefreshSessionMutation,
|
||||||
} from "../shared";
|
} from "../shared";
|
||||||
import { getCurrentSession } from "../shared/api";
|
import { getCurrentSession } from "../shared/api";
|
||||||
import type { ActiveCompany, AuthSession, CompanySession } from "../shared/entities";
|
import type { ActiveCompany, AuthSession, CompanySession } from "../shared/entities";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
resetIdentityAuthSessionRuntimeHandlers,
|
resetIdentityAuthSessionRuntimeHandlers,
|
||||||
setIdentityAuthSessionRuntimeHandlers,
|
setIdentityAuthSessionRuntimeHandlers,
|
||||||
} from "./identity-auth-session.runtime";
|
} from "./identity-auth-session.runtime";
|
||||||
|
|
||||||
export interface IdentityAuthSessionContextValue {
|
export interface IdentityAuthSessionContextValue {
|
||||||
session: AuthSession | null;
|
session: AuthSession | null;
|
||||||
account: AuthSession["account"] | null;
|
account: AuthSession["account"] | null;
|
||||||
companySession: CompanySession;
|
companySession: CompanySession;
|
||||||
availableCompanies: ActiveCompany[];
|
availableCompanies: ActiveCompany[];
|
||||||
activeCompany: ActiveCompany | null;
|
activeCompany: ActiveCompany | null;
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
login: (params: LoginForm) => Promise<AuthSession>;
|
login: (params: LoginForm) => Promise<AuthSession>;
|
||||||
logout: () => Promise<void>;
|
logout: () => Promise<void>;
|
||||||
restoreSession: () => Promise<AuthSession | null>;
|
restoreSession: () => Promise<AuthSession | null>;
|
||||||
refreshSession: () => Promise<AuthSession | null>;
|
refreshSession: () => Promise<AuthSession | null>;
|
||||||
refreshAccessToken: () => Promise<string | null>;
|
refreshAccessToken: () => Promise<string | null>;
|
||||||
selectActiveCompany: (companyId: string) => ActiveCompany | null;
|
selectActiveCompany: (companyId: string) => ActiveCompany | null;
|
||||||
changeActiveCompany: (companyId: string) => Promise<ActiveCompany | null>;
|
changeActiveCompany: (companyId: string) => Promise<ActiveCompany | null>;
|
||||||
updateActiveCompany: (company: {
|
updateActiveCompany: (company: {
|
||||||
id: string;
|
id: string;
|
||||||
legalName: string;
|
legalName: string;
|
||||||
tradeName: string | null;
|
tradeName: string | null;
|
||||||
}) => void;
|
}) => void;
|
||||||
updateAccount: (account: {
|
updateAccount: (account: {
|
||||||
id: string;
|
id: string;
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
avatarUrl: string | null;
|
avatarUrl: string | null;
|
||||||
languageCode: string;
|
languageCode: string;
|
||||||
}) => void;
|
}) => void;
|
||||||
getAuthenticatedRedirectPath: (params?: {
|
getAuthenticatedRedirectPath: (params?: {
|
||||||
returnTo?: string | null;
|
returnTo?: string | null;
|
||||||
fallbackPath?: string;
|
fallbackPath?: string;
|
||||||
}) => string;
|
}) => string;
|
||||||
clearSession: () => void;
|
clearSession: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IdentityAuthSessionContext = createContext<IdentityAuthSessionContextValue | undefined>(
|
const IdentityAuthSessionContext = createContext<IdentityAuthSessionContextValue | undefined>(
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
const EMPTY_COMPANY_SESSION: CompanySession = {
|
const EMPTY_COMPANY_SESSION: CompanySession = {
|
||||||
availableCompanies: [],
|
availableCompanies: [],
|
||||||
activeCompany: null,
|
activeCompany: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function IdentityAuthSessionProvider({ children }: { children: React.ReactNode }) {
|
export function IdentityAuthSessionProvider({ children }: { children: React.ReactNode }) {
|
||||||
const dataSource = useDataSource();
|
const dataSource = useDataSource();
|
||||||
const loginMutation = useLoginMutation();
|
const loginMutation = useLoginMutation();
|
||||||
const logoutMutation = useLogoutMutation();
|
const logoutMutation = useLogoutMutation();
|
||||||
const refreshSessionMutation = useRefreshSessionMutation();
|
const refreshSessionMutation = useRefreshSessionMutation();
|
||||||
|
|
||||||
const [session, setSession] = useState<AuthSession | null>(null);
|
const [session, setSession] = useState<AuthSession | null>(null);
|
||||||
const [companySession, setCompanySession] = useState<CompanySession>(EMPTY_COMPANY_SESSION);
|
const [companySession, setCompanySession] = useState<CompanySession>(EMPTY_COMPANY_SESSION);
|
||||||
const [isRestoringSession, setIsRestoringSession] = useState(authTokenStorage.hasAccessToken());
|
const [isRestoringSession, setIsRestoringSession] = useState(authTokenStorage.hasAccessToken());
|
||||||
|
|
||||||
const clearSession = useCallback(() => {
|
const clearSession = useCallback(() => {
|
||||||
authTokenStorage.clear();
|
authTokenStorage.clear();
|
||||||
activeCompanyStorage.clear();
|
activeCompanyStorage.clear();
|
||||||
setSession(null);
|
setSession(null);
|
||||||
setCompanySession(EMPTY_COMPANY_SESSION);
|
setCompanySession(EMPTY_COMPANY_SESSION);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const hydrateCompanySession = useCallback(
|
const hydrateCompanySession = useCallback(
|
||||||
async (accessToken: string) => {
|
async (accessToken: string) => {
|
||||||
const response = await findAvailableCompanies(dataSource, accessToken);
|
const response = await findAvailableCompanies(dataSource, accessToken);
|
||||||
const parsedResponse = AvailableCompaniesResponseDTOSchema.safeParse(response);
|
const parsedResponse = AvailableCompaniesResponseDTOSchema.safeParse(response);
|
||||||
|
|
||||||
if (!parsedResponse.success) {
|
if (!parsedResponse.success) {
|
||||||
throw new Error("Invalid available companies response");
|
throw new Error("Invalid available companies response");
|
||||||
}
|
}
|
||||||
|
|
||||||
const availableCompanies = parsedResponse.data.companies.map(mapAvailableCompany);
|
const availableCompanies = parsedResponse.data.companies.map(mapAvailableCompany);
|
||||||
const nextCompanySession = resolveCompanySession({
|
const nextCompanySession = resolveCompanySession({
|
||||||
companies: availableCompanies,
|
companies: availableCompanies,
|
||||||
persistedActiveCompanyId: activeCompanyStorage.getActiveCompanyId(),
|
persistedActiveCompanyId: activeCompanyStorage.getActiveCompanyId(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (nextCompanySession.activeCompany) {
|
if (nextCompanySession.activeCompany) {
|
||||||
activeCompanyStorage.setActiveCompanyId(nextCompanySession.activeCompany.id);
|
activeCompanyStorage.setActiveCompanyId(nextCompanySession.activeCompany.id);
|
||||||
} else {
|
} else {
|
||||||
activeCompanyStorage.clear();
|
activeCompanyStorage.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
setCompanySession(nextCompanySession);
|
setCompanySession(nextCompanySession);
|
||||||
|
|
||||||
return nextCompanySession;
|
return nextCompanySession;
|
||||||
},
|
},
|
||||||
[dataSource]
|
[dataSource]
|
||||||
);
|
);
|
||||||
|
|
||||||
const restoreSession = useCallback(async () => {
|
const restoreSession = useCallback(async () => {
|
||||||
const tokens = authTokenStorage.getTokens();
|
const tokens = authTokenStorage.getTokens();
|
||||||
|
|
||||||
if (!tokens.accessToken) {
|
if (!tokens.accessToken) {
|
||||||
clearSession();
|
clearSession();
|
||||||
setIsRestoringSession(false);
|
setIsRestoringSession(false);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsRestoringSession(true);
|
setIsRestoringSession(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await getCurrentSession(dataSource, tokens.accessToken);
|
const response = await getCurrentSession(dataSource, tokens.accessToken);
|
||||||
const restoredSession = mapCurrentSessionToAuthSession(response, {
|
const restoredSession = mapCurrentSessionToAuthSession(response, {
|
||||||
accessToken: tokens.accessToken,
|
accessToken: tokens.accessToken,
|
||||||
refreshToken: tokens.refreshToken ?? "",
|
refreshToken: tokens.refreshToken ?? "",
|
||||||
});
|
});
|
||||||
|
|
||||||
await hydrateCompanySession(tokens.accessToken);
|
await hydrateCompanySession(tokens.accessToken);
|
||||||
setSession(restoredSession);
|
setSession(restoredSession);
|
||||||
|
|
||||||
return restoredSession;
|
return restoredSession;
|
||||||
} catch {
|
} catch {
|
||||||
clearSession();
|
clearSession();
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
setIsRestoringSession(false);
|
setIsRestoringSession(false);
|
||||||
}
|
}
|
||||||
}, [clearSession, dataSource, hydrateCompanySession]);
|
}, [clearSession, dataSource, hydrateCompanySession]);
|
||||||
|
|
||||||
const login = useCallback(
|
const login = useCallback(
|
||||||
async (params: LoginForm) => {
|
async (params: LoginForm) => {
|
||||||
const nextSession = await loginMutation.mutateAsync(params);
|
const nextSession = await loginMutation.mutateAsync(params);
|
||||||
|
|
||||||
authTokenStorage.setTokens({
|
authTokenStorage.setTokens({
|
||||||
accessToken: nextSession.accessToken,
|
accessToken: nextSession.accessToken,
|
||||||
refreshToken: nextSession.refreshToken,
|
refreshToken: nextSession.refreshToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
activeCompanyStorage.clear();
|
activeCompanyStorage.clear();
|
||||||
await hydrateCompanySession(nextSession.accessToken);
|
await hydrateCompanySession(nextSession.accessToken);
|
||||||
setSession(nextSession);
|
setSession(nextSession);
|
||||||
|
|
||||||
return nextSession;
|
return nextSession;
|
||||||
},
|
},
|
||||||
[hydrateCompanySession, loginMutation]
|
[hydrateCompanySession, loginMutation]
|
||||||
);
|
);
|
||||||
|
|
||||||
const logout = useCallback(async () => {
|
const logout = useCallback(async () => {
|
||||||
const tokens = authTokenStorage.getTokens();
|
const tokens = authTokenStorage.getTokens();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (tokens.accessToken) {
|
if (tokens.accessToken) {
|
||||||
await logoutMutation.mutateAsync({
|
await logoutMutation.mutateAsync({
|
||||||
accessToken: tokens.accessToken,
|
accessToken: tokens.accessToken,
|
||||||
refreshToken: tokens.refreshToken,
|
refreshToken: tokens.refreshToken,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
clearSession();
|
clearSession();
|
||||||
}
|
}
|
||||||
}, [clearSession, logoutMutation]);
|
}, [clearSession, logoutMutation]);
|
||||||
|
|
||||||
const refreshSession = useCallback(async () => {
|
const refreshSession = useCallback(async () => {
|
||||||
const tokens = authTokenStorage.getTokens();
|
const tokens = authTokenStorage.getTokens();
|
||||||
|
|
||||||
if (!tokens.refreshToken) {
|
if (!tokens.refreshToken) {
|
||||||
clearSession();
|
clearSession();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const refreshedTokens = await refreshSessionMutation.mutateAsync({
|
const refreshedTokens = await refreshSessionMutation.mutateAsync({
|
||||||
refreshToken: tokens.refreshToken,
|
refreshToken: tokens.refreshToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
authTokenStorage.setTokens(refreshedTokens);
|
authTokenStorage.setTokens(refreshedTokens);
|
||||||
await hydrateCompanySession(refreshedTokens.accessToken);
|
await hydrateCompanySession(refreshedTokens.accessToken);
|
||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
const refreshedSession: AuthSession = {
|
const refreshedSession: AuthSession = {
|
||||||
...session,
|
...session,
|
||||||
accessToken: refreshedTokens.accessToken,
|
accessToken: refreshedTokens.accessToken,
|
||||||
refreshToken: refreshedTokens.refreshToken,
|
refreshToken: refreshedTokens.refreshToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
setSession(refreshedSession);
|
setSession(refreshedSession);
|
||||||
return refreshedSession;
|
return refreshedSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentSessionResponse = await getCurrentSession(
|
const currentSessionResponse = await getCurrentSession(
|
||||||
dataSource,
|
dataSource,
|
||||||
refreshedTokens.accessToken
|
refreshedTokens.accessToken
|
||||||
);
|
);
|
||||||
const refreshedSession = mapCurrentSessionToAuthSession(currentSessionResponse, {
|
const refreshedSession = mapCurrentSessionToAuthSession(currentSessionResponse, {
|
||||||
accessToken: refreshedTokens.accessToken,
|
accessToken: refreshedTokens.accessToken,
|
||||||
refreshToken: refreshedTokens.refreshToken,
|
refreshToken: refreshedTokens.refreshToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
setSession(refreshedSession);
|
setSession(refreshedSession);
|
||||||
|
|
||||||
return refreshedSession;
|
return refreshedSession;
|
||||||
} catch {
|
} catch {
|
||||||
clearSession();
|
clearSession();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, [clearSession, dataSource, hydrateCompanySession, refreshSessionMutation, session]);
|
}, [clearSession, dataSource, hydrateCompanySession, refreshSessionMutation, session]);
|
||||||
|
|
||||||
const refreshAccessToken = useCallback(async () => {
|
const refreshAccessToken = useCallback(async () => {
|
||||||
const refreshedSession = await refreshSession();
|
const refreshedSession = await refreshSession();
|
||||||
return refreshedSession?.accessToken ?? null;
|
return refreshedSession?.accessToken ?? null;
|
||||||
}, [refreshSession]);
|
}, [refreshSession]);
|
||||||
|
|
||||||
const selectActiveCompany = useCallback(
|
const selectActiveCompany = useCallback(
|
||||||
(companyId: string) => {
|
(companyId: string) => {
|
||||||
if (companySession.activeCompany?.id === companyId) {
|
if (companySession.activeCompany?.id === companyId) {
|
||||||
return companySession.activeCompany;
|
return companySession.activeCompany;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextActiveCompany =
|
const nextActiveCompany =
|
||||||
companySession.availableCompanies.find((company) => company.id === companyId) ?? null;
|
companySession.availableCompanies.find((company) => company.id === companyId) ?? null;
|
||||||
|
|
||||||
if (!nextActiveCompany) {
|
if (!nextActiveCompany) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
activeCompanyStorage.setActiveCompanyId(nextActiveCompany.id);
|
activeCompanyStorage.setActiveCompanyId(nextActiveCompany.id);
|
||||||
setCompanySession((currentSession) => ({
|
setCompanySession((currentSession) => ({
|
||||||
...currentSession,
|
...currentSession,
|
||||||
activeCompany: nextActiveCompany,
|
activeCompany: nextActiveCompany,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return nextActiveCompany;
|
return nextActiveCompany;
|
||||||
},
|
},
|
||||||
[companySession.activeCompany, companySession.availableCompanies]
|
[companySession.activeCompany, companySession.availableCompanies]
|
||||||
);
|
);
|
||||||
|
|
||||||
const changeActiveCompany = useCallback(
|
const changeActiveCompany = useCallback(
|
||||||
async (companyId: string) => {
|
async (companyId: string) => {
|
||||||
return selectActiveCompany(companyId);
|
return selectActiveCompany(companyId);
|
||||||
},
|
},
|
||||||
[selectActiveCompany]
|
[selectActiveCompany]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateActiveCompany = useCallback(
|
const updateActiveCompany = useCallback(
|
||||||
(company: { id: string; legalName: string; tradeName: string | null }) => {
|
(company: { id: string; legalName: string; tradeName: string | null }) => {
|
||||||
setCompanySession((currentSession) => {
|
setCompanySession((currentSession) => {
|
||||||
const availableCompanies = currentSession.availableCompanies.map((item) =>
|
const availableCompanies = currentSession.availableCompanies.map((item) =>
|
||||||
item.id === company.id
|
item.id === company.id
|
||||||
? {
|
? {
|
||||||
...item,
|
...item,
|
||||||
legalName: company.legalName,
|
legalName: company.legalName,
|
||||||
tradeName: company.tradeName,
|
tradeName: company.tradeName,
|
||||||
}
|
}
|
||||||
: item
|
: item
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeCompany =
|
const activeCompany =
|
||||||
currentSession.activeCompany?.id === company.id
|
currentSession.activeCompany?.id === company.id
|
||||||
? {
|
? {
|
||||||
...currentSession.activeCompany,
|
...currentSession.activeCompany,
|
||||||
legalName: company.legalName,
|
legalName: company.legalName,
|
||||||
tradeName: company.tradeName,
|
tradeName: company.tradeName,
|
||||||
}
|
}
|
||||||
: currentSession.activeCompany;
|
: currentSession.activeCompany;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableCompanies,
|
availableCompanies,
|
||||||
activeCompany,
|
activeCompany,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateAccount = useCallback(
|
const updateAccount = useCallback(
|
||||||
(account: {
|
(account: {
|
||||||
id: string;
|
id: string;
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
avatarUrl: string | null;
|
avatarUrl: string | null;
|
||||||
languageCode: string;
|
languageCode: string;
|
||||||
}) => {
|
}) => {
|
||||||
setSession((currentSession) => {
|
setSession((currentSession) => {
|
||||||
if (!currentSession || currentSession.account.id !== account.id) {
|
if (!currentSession || currentSession.account.id !== account.id) {
|
||||||
return currentSession;
|
return currentSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...currentSession,
|
...currentSession,
|
||||||
account: {
|
account: {
|
||||||
...currentSession.account,
|
...currentSession.account,
|
||||||
email: account.email,
|
email: account.email,
|
||||||
name: account.name,
|
name: account.name,
|
||||||
avatarUrl: account.avatarUrl,
|
avatarUrl: account.avatarUrl,
|
||||||
languageCode: account.languageCode,
|
languageCode: account.languageCode,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getAuthenticatedRedirectPath = useCallback(
|
const getAuthenticatedRedirectPath = useCallback(
|
||||||
(params?: { returnTo?: string | null; fallbackPath?: string }) => {
|
(params?: { returnTo?: string | null; fallbackPath?: string }) => {
|
||||||
return resolveAuthenticatedRedirectPath({
|
return resolveAuthenticatedRedirectPath({
|
||||||
companySession,
|
companySession,
|
||||||
fallbackPath: params?.fallbackPath ?? "/proformas",
|
fallbackPath: params?.fallbackPath ?? "/proformas",
|
||||||
returnTo: params?.returnTo,
|
returnTo: params?.returnTo,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[companySession]
|
[companySession]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
restoreSession();
|
restoreSession();
|
||||||
}, [restoreSession]);
|
}, [restoreSession]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIdentityAuthSessionRuntimeHandlers({
|
setIdentityAuthSessionRuntimeHandlers({
|
||||||
clearSession,
|
clearSession,
|
||||||
refreshAccessToken,
|
refreshAccessToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
resetIdentityAuthSessionRuntimeHandlers();
|
resetIdentityAuthSessionRuntimeHandlers();
|
||||||
};
|
};
|
||||||
}, [clearSession, refreshAccessToken]);
|
}, [clearSession, refreshAccessToken]);
|
||||||
|
|
||||||
const value = useMemo<IdentityAuthSessionContextValue>(
|
const value = useMemo<IdentityAuthSessionContextValue>(
|
||||||
() => ({
|
() => ({
|
||||||
session,
|
session,
|
||||||
account: session?.account ?? null,
|
account: session?.account ?? null,
|
||||||
companySession,
|
companySession,
|
||||||
availableCompanies: companySession.availableCompanies,
|
availableCompanies: companySession.availableCompanies,
|
||||||
activeCompany: companySession.activeCompany,
|
activeCompany: companySession.activeCompany,
|
||||||
isAuthenticated: Boolean(session),
|
isAuthenticated: Boolean(session),
|
||||||
isLoading:
|
isLoading:
|
||||||
isRestoringSession ||
|
isRestoringSession ||
|
||||||
loginMutation.isPending ||
|
loginMutation.isPending ||
|
||||||
logoutMutation.isPending ||
|
logoutMutation.isPending ||
|
||||||
refreshSessionMutation.isPending,
|
refreshSessionMutation.isPending,
|
||||||
login,
|
login,
|
||||||
logout,
|
logout,
|
||||||
restoreSession,
|
restoreSession,
|
||||||
refreshSession,
|
refreshSession,
|
||||||
refreshAccessToken,
|
refreshAccessToken,
|
||||||
selectActiveCompany,
|
selectActiveCompany,
|
||||||
changeActiveCompany,
|
changeActiveCompany,
|
||||||
updateActiveCompany,
|
updateActiveCompany,
|
||||||
updateAccount,
|
updateAccount,
|
||||||
getAuthenticatedRedirectPath,
|
getAuthenticatedRedirectPath,
|
||||||
clearSession,
|
clearSession,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
changeActiveCompany,
|
changeActiveCompany,
|
||||||
clearSession,
|
clearSession,
|
||||||
companySession,
|
companySession,
|
||||||
getAuthenticatedRedirectPath,
|
getAuthenticatedRedirectPath,
|
||||||
isRestoringSession,
|
isRestoringSession,
|
||||||
login,
|
login,
|
||||||
loginMutation.isPending,
|
loginMutation.isPending,
|
||||||
logout,
|
logout,
|
||||||
logoutMutation.isPending,
|
logoutMutation.isPending,
|
||||||
refreshAccessToken,
|
refreshAccessToken,
|
||||||
refreshSession,
|
refreshSession,
|
||||||
refreshSessionMutation.isPending,
|
refreshSessionMutation.isPending,
|
||||||
restoreSession,
|
restoreSession,
|
||||||
selectActiveCompany,
|
selectActiveCompany,
|
||||||
updateActiveCompany,
|
updateActiveCompany,
|
||||||
updateAccount,
|
updateAccount,
|
||||||
session,
|
session,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IdentityAuthSessionContext.Provider value={value}>
|
<IdentityAuthSessionContext.Provider value={value}>
|
||||||
{children}
|
{children}
|
||||||
</IdentityAuthSessionContext.Provider>
|
</IdentityAuthSessionContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useIdentityAuthSession() {
|
export function useIdentityAuthSession() {
|
||||||
const context = useContext(IdentityAuthSessionContext);
|
const context = useContext(IdentityAuthSessionContext);
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error("useIdentityAuthSession must be used within a IdentityAuthSessionProvider");
|
throw new Error("useIdentityAuthSession must be used within a IdentityAuthSessionProvider");
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user