diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 28a493ec..eb48ad38 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -628,11 +628,13 @@ export const apiClient = { }, onboarding: { - get: (guildId: string) => api.get(`/api/${guildId}/onboarding`), + get: (guildId: string) => + api.get(`/api/${guildId}/onboarding`, SKIP_ERROR_TOAST), update: ( guildId: string, body: { current_step?: number; completed?: boolean; skipped?: boolean }, - ) => api.post<{ success: boolean }>(`/api/${guildId}/onboarding`, body), + config?: AxiosRequestConfig, + ) => api.post<{ success: boolean }>(`/api/${guildId}/onboarding`, body, config), getFeaturedListings: (guildId: string) => api.get(`/api/${guildId}/gallery/featured`), }, diff --git a/frontend/src/pages/manage/GuildLayout.tsx b/frontend/src/pages/manage/GuildLayout.tsx index 502b154f..6a860dcf 100644 --- a/frontend/src/pages/manage/GuildLayout.tsx +++ b/frontend/src/pages/manage/GuildLayout.tsx @@ -16,7 +16,7 @@ export default function GuildLayout() { const navigate = useNavigate(); const { selectedGuild, selectGuild, updateGuild } = useGuildStore(); const updateGuildPermission = useAuthStore((s) => s.updateGuildPermission); - const { setState: setOnboardingState } = useOnboardingStore(); + const { setState: setOnboardingState, reset: resetOnboarding } = useOnboardingStore(); const [verified, setVerified] = useState(false); const [bootstrapReady, setBootstrapReady] = useState(false); @@ -32,6 +32,7 @@ export default function GuildLayout() { setVerified(false); setBootstrapReady(false); + resetOnboarding(); let cancelled = false; @@ -155,6 +156,7 @@ export default function GuildLayout() { updateGuildPermission, navigate, setOnboardingState, + resetOnboarding, isTranscriptView, ]); @@ -177,7 +179,7 @@ export default function GuildLayout() { return ( - {guildId && (selectedGuild?.permission_level ?? 0) >= 1 && ( + {guildId && (selectedGuild?.permission_level ?? 0) >= 2 && ( )} diff --git a/frontend/src/pages/manage/setup/SetupLayout.tsx b/frontend/src/pages/manage/setup/SetupLayout.tsx index 82902ef1..4000577d 100644 --- a/frontend/src/pages/manage/setup/SetupLayout.tsx +++ b/frontend/src/pages/manage/setup/SetupLayout.tsx @@ -67,6 +67,13 @@ function SetupLayoutContent() { return; } + if ((g.permission_level ?? 0) < 2) { + selectGuild(null); + toast.warning("You need administrator permissions to access the setup wizard."); + navigate("/", { replace: true }); + return; + } + setVerified(false); const verifyAndLoad = async () => { diff --git a/frontend/src/pages/manage/setup/components/OnboardingBanner.tsx b/frontend/src/pages/manage/setup/components/OnboardingBanner.tsx index c4f7058f..b2bf0b90 100644 --- a/frontend/src/pages/manage/setup/components/OnboardingBanner.tsx +++ b/frontend/src/pages/manage/setup/components/OnboardingBanner.tsx @@ -1,6 +1,6 @@ import type { FC } from "react"; import { Link } from "react-router"; -import { apiClient } from "@/lib/api"; +import { apiClient, SKIP_ERROR_TOAST } from "@/lib/api"; import { useOnboardingStore } from "@/stores/onboarding"; import Button from "@/components/Button"; import { useFeatureFlag } from "@/hooks/useFeatureFlag"; @@ -17,13 +17,20 @@ const OnboardingBanner: FC = ({ guildId }) => { guildId, ); - if (!state || state.onboarding_completed || state.skipped || flagLoading || !wizardEnabled) { + if ( + !state || + state.guild_id !== guildId || + state.onboarding_completed || + state.skipped || + flagLoading || + !wizardEnabled + ) { return null; } const handleDismiss = async () => { try { - await apiClient.onboarding.update(guildId, { skipped: true }); + await apiClient.onboarding.update(guildId, { skipped: true }, SKIP_ERROR_TOAST); setOnboardingState({ ...state, skipped: true }); } catch { // Silently fail - the banner will persist until next page load