feat(admin-web/auth): support phone-or-email login and dim shell on expiry

Login form takes a phone-or-email identifier; user info now exposes phone
so the shell can fall back through name → phone → email. When membership
expires, the app stays on the current route but renders a minimal blocked
state in the shell instead of redirecting to a dedicated page; an Axios
interceptor flips the local session into the blocked state when the API
returns trial/subscription errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-29 00:01:47 +08:00
parent ee21f512a9
commit 62b824520c
10 changed files with 170 additions and 33 deletions
+18
View File
@@ -118,6 +118,7 @@ import {
clearStoredSession,
getStoredAccessToken,
getStoredRefreshToken,
markStoredMembershipBlocked,
readStoredSession,
setStoredTokens,
} from "./session";
@@ -271,6 +272,23 @@ export const apiClient = createApiClient({
},
});
const membershipBlockedErrors = new Set([
"trial_plan_expired",
"subscription_required",
"subscription_inactive",
]);
apiClient.raw.interceptors.response.use(
(response) => response,
(error) => {
if (error instanceof ApiClientError && membershipBlockedErrors.has(error.message)) {
markStoredMembershipBlocked(error.message);
}
return Promise.reject(error);
},
);
export const authApi = {
login(payload: LoginRequest) {
return publicClient.post<LoginResponse, LoginRequest>("/api/auth/login", payload);