feat(pwa): просмотр чужого экрана больше не выбрасывает из своего аккаунта
Сотрудник, вошедший водителем, при переключении на чужую карточку терял собственный вход: токен один на приложение, и «посмотреть, как выглядит у другого» означало заново входить через Telegram. Теперь свой сеанс откладывается и возвращается кнопкой «Вернуться к своему аккаунту». Откладывается ровно один раз — на переходе из обычного сеанса: смена водителя внутри просмотра не должна подменять отложенное чужим токеном. Заодно вход для сотрудника достижим изнутри приложения: длинный тап по названию в шапке ведёт на /dev. Ссылкой на экране это не делаем — водителю она ни к чему, а сотруднику иначе приходится набирать адрес руками. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,20 +10,33 @@ export interface ViewAs {
|
||||
driverName: string | null;
|
||||
}
|
||||
|
||||
/** Собственный сеанс, отложенный на время просмотра чужого. */
|
||||
interface OwnSession {
|
||||
token: string;
|
||||
driverId: number | null;
|
||||
}
|
||||
|
||||
interface AuthState extends ViewAs {
|
||||
token: string | null;
|
||||
driverId: number | null;
|
||||
/** Сеанс, к которому вернёт «выйти из просмотра». null — возвращаться некуда. */
|
||||
own: OwnSession | null;
|
||||
setSession: (token: string, driverId: number, view?: Partial<ViewAs>) => void;
|
||||
/** Начать просмотр от лица водителя, отложив собственный вход. */
|
||||
startImpersonation: (token: string, driverId: number, driverName: string) => void;
|
||||
/** Вернуться к себе. true — вернулись, false — своего входа не было. */
|
||||
stopImpersonation: () => boolean;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useAuth = create<AuthState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
(set, get) => ({
|
||||
token: null,
|
||||
driverId: null,
|
||||
impersonated: false,
|
||||
driverName: null,
|
||||
own: null,
|
||||
setSession: (token, driverId, view) =>
|
||||
set({
|
||||
token,
|
||||
@@ -31,7 +44,35 @@ export const useAuth = create<AuthState>()(
|
||||
impersonated: view?.impersonated ?? false,
|
||||
driverName: view?.driverName ?? null,
|
||||
}),
|
||||
clear: () => set({ token: null, driverId: null, impersonated: false, driverName: null }),
|
||||
startImpersonation: (token, driverId, driverName) => {
|
||||
const s = get();
|
||||
// Свой вход откладываем ОДИН раз — при переходе из обычного сеанса. Смена
|
||||
// водителя внутри просмотра не должна затирать отложенное собственным
|
||||
// чужим токеном, иначе «вернуться к себе» вернёт к предыдущему водителю.
|
||||
const own = s.impersonated
|
||||
? s.own
|
||||
: s.token
|
||||
? { token: s.token, driverId: s.driverId }
|
||||
: null;
|
||||
set({ token, driverId, impersonated: true, driverName, own });
|
||||
},
|
||||
stopImpersonation: () => {
|
||||
const own = get().own;
|
||||
if (!own) {
|
||||
set({ token: null, driverId: null, impersonated: false, driverName: null });
|
||||
return false;
|
||||
}
|
||||
set({
|
||||
token: own.token,
|
||||
driverId: own.driverId,
|
||||
impersonated: false,
|
||||
driverName: null,
|
||||
own: null,
|
||||
});
|
||||
return true;
|
||||
},
|
||||
clear: () =>
|
||||
set({ token: null, driverId: null, impersonated: false, driverName: null, own: null }),
|
||||
}),
|
||||
{ name: "pp-driver-auth" }
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user