fix: credentials lost on refresh + admin UI improvements + CI safe deploy
CI/CD / CI · API (dotnet build + test) (push) Successful in 39s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 30s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m2s
CI/CD / CI · Admin Web (tsc) (push) Failing after 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Has been skipped
CI/CD / CI · API (dotnet build + test) (push) Successful in 39s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 30s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m2s
CI/CD / CI · Admin Web (tsc) (push) Failing after 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Has been skipped
- dashboard layout: wait for Zustand _hasHydrated before redirecting to /login (was redirecting on first render before localStorage was read) - admin shell: same fix using new _hasHydrated on admin auth store - admin-auth.store: add _hasHydrated + onRehydrateStorage to mirror merchant store - AdminPlansScreen: replace direct cache mutation with per-plan PlanCard component that owns its own useState — fixes other plans disappearing after save - AdminSettingsScreen: detect boolean values and render iOS-style Toggle switches - AdminIntegrationsScreen: replace all <input type=checkbox> with Toggle switches; replace OpenAI model text input with <select> dropdown (gpt-4o-mini/4o/4-turbo/4/3.5) - blog editor: fix form never syncing existing post data into state (editing was broken); all fields now use local form state, save uses form directly - blog links: fix broken relative hrefs (website/blog/new → /admin/website/blog/new) and back button using proper Link components - ci-cd: remove image prune step entirely — never removes containers or images Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,20 @@ import type { AuthTokenResponse } from "@/lib/api/types";
|
||||
|
||||
interface AdminAuthState {
|
||||
user: AuthTokenResponse | null;
|
||||
/** True once Zustand has finished rehydrating from localStorage. */
|
||||
_hasHydrated: boolean;
|
||||
setAuth: (user: AuthTokenResponse) => void;
|
||||
clearAuth: () => void;
|
||||
isAuthenticated: () => boolean;
|
||||
_setHasHydrated: (v: boolean) => void;
|
||||
}
|
||||
|
||||
export const useAdminAuthStore = create<AdminAuthState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
user: null,
|
||||
_hasHydrated: false,
|
||||
_setHasHydrated: (v) => set({ _hasHydrated: v }),
|
||||
setAuth: (user) => {
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem("meezi_admin_access_token", user.accessToken);
|
||||
@@ -29,6 +34,11 @@ export const useAdminAuthStore = create<AdminAuthState>()(
|
||||
},
|
||||
isAuthenticated: () => !!get().user?.accessToken,
|
||||
}),
|
||||
{ name: "meezi_admin_auth" }
|
||||
{
|
||||
name: "meezi_admin_auth",
|
||||
onRehydrateStorage: () => (state) => {
|
||||
state?._setHasHydrated(true);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user