initial commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import { createContext, useContext, useEffect, useState, useCallback, type ReactNode } from 'react';
|
||||
import { useSearchParams, useNavigate } from 'react-router-dom';
|
||||
import { pb } from '../../lib/pocketbase';
|
||||
|
||||
interface ImpersonatedTechInfo {
|
||||
id: string;
|
||||
email: string;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
interface TechnicianContextValue {
|
||||
effectiveUserId: string;
|
||||
isImpersonating: boolean;
|
||||
impersonatedTech: ImpersonatedTechInfo | null;
|
||||
stopImpersonation: () => void;
|
||||
}
|
||||
|
||||
const TechnicianContext = createContext<TechnicianContextValue>({
|
||||
effectiveUserId: '',
|
||||
isImpersonating: false,
|
||||
impersonatedTech: null,
|
||||
stopImpersonation: () => {},
|
||||
});
|
||||
|
||||
export function TechnicianProvider({ children }: { children: ReactNode }) {
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
const viewAs = searchParams.get('view_as');
|
||||
const authUserId = pb.authStore.model?.id as string | undefined;
|
||||
const [impersonatedTech, setImpersonatedTech] = useState<ImpersonatedTechInfo | null>(null);
|
||||
|
||||
const isImpersonating = !!viewAs && viewAs !== authUserId;
|
||||
const effectiveUserId = isImpersonating ? viewAs! : (authUserId || '');
|
||||
|
||||
useEffect(() => {
|
||||
if (isImpersonating && viewAs) {
|
||||
pb.collection('users').getOne(viewAs).then((user) => {
|
||||
setImpersonatedTech({
|
||||
id: user.id,
|
||||
email: user.email as string,
|
||||
displayName: user.displayName as string | undefined,
|
||||
});
|
||||
}).catch(() => {
|
||||
setImpersonatedTech(null);
|
||||
});
|
||||
} else {
|
||||
setImpersonatedTech(null);
|
||||
}
|
||||
}, [isImpersonating, viewAs]);
|
||||
|
||||
const stopImpersonation = useCallback(() => {
|
||||
navigate('/team');
|
||||
}, [navigate]);
|
||||
|
||||
return (
|
||||
<TechnicianContext.Provider
|
||||
value={{
|
||||
effectiveUserId,
|
||||
isImpersonating,
|
||||
impersonatedTech,
|
||||
stopImpersonation,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</TechnicianContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useTechnicianContext(): TechnicianContextValue {
|
||||
return useContext(TechnicianContext);
|
||||
}
|
||||
|
||||
export function useTechnicianNav() {
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
const viewAs = searchParams.get('view_as');
|
||||
|
||||
const buildTechUrl = useCallback(
|
||||
(path: string): string => {
|
||||
if (!viewAs) return path;
|
||||
const separator = path.includes('?') ? '&' : '?';
|
||||
return `${path}${separator}view_as=${encodeURIComponent(viewAs)}`;
|
||||
},
|
||||
[viewAs],
|
||||
);
|
||||
|
||||
const navigateTech = useCallback(
|
||||
(path: string, opts?: { replace?: boolean; state?: unknown }) => {
|
||||
navigate(buildTechUrl(path), opts);
|
||||
},
|
||||
[navigate, buildTechUrl],
|
||||
);
|
||||
|
||||
return { buildTechUrl, navigateTech };
|
||||
}
|
||||
Reference in New Issue
Block a user