diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 40b4b577..3e47f854 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -143,6 +143,9 @@ function DashboardContent({ const [showWorkspaceSettings, setShowWorkspaceSettings] = useState(false); const [showWorkspaceShare, setShowWorkspaceShare] = useState(false); + // Manual open state for the raffle popup (re-opened via the share-count badge). + const [showRafflePopup, setShowRafflePopup] = useState(false); + const showSignInPrompt = !!session?.user?.isAnonymous && !isLoadingWorkspace && @@ -289,6 +292,8 @@ function DashboardContent({ currentWorkspaceId={currentWorkspaceId} isLoadingWorkspace={isLoadingWorkspace} onOpenFullShare={() => setShowWorkspaceShare(true)} + manuallyOpen={showRafflePopup} + onManuallyClose={() => setShowRafflePopup(false)} /> setShowRafflePopup(true)} /> ) : undefined } diff --git a/src/components/modals/RafflePopup.tsx b/src/components/modals/RafflePopup.tsx index 87ba1bd4..e4379bcc 100644 --- a/src/components/modals/RafflePopup.tsx +++ b/src/components/modals/RafflePopup.tsx @@ -23,6 +23,10 @@ interface RafflePopupProps { currentWorkspaceId: string | null; isLoadingWorkspace: boolean; onOpenFullShare?: () => void; + /** Force the popup open regardless of dismissal state (e.g. user clicked the share-count badge). */ + manuallyOpen?: boolean; + /** Called when a manually-opened popup is closed; parent should clear its manual-open state. */ + onManuallyClose?: () => void; } const FEATURE_KEY = "midterms-raffle-2026-04"; @@ -33,6 +37,8 @@ export function RafflePopup({ currentWorkspaceId, isLoadingWorkspace, onOpenFullShare, + manuallyOpen = false, + onManuallyClose, }: RafflePopupProps) { const { data: session } = useSession(); const { isNew, dismiss } = useNewFeature({ @@ -46,16 +52,17 @@ export function RafflePopup({ const [isLoadingShareLink, setIsLoadingShareLink] = useState(false); const [copied, setCopied] = useState(false); - const canRender = + const canShowPopup = !!currentWorkspaceId && !isLoadingWorkspace && !!workspace && session?.user?.isAnonymous !== true && - workspace?.userId === session?.user?.id && - isNew; + workspace?.userId === session?.user?.id; + + const isOpen = canShowPopup && (isNew || manuallyOpen); useEffect(() => { - if (!canRender || !workspace) return; + if (!isOpen || !workspace) return; const controller = new AbortController(); setIsLoadingShareLink(true); @@ -81,12 +88,17 @@ export function RafflePopup({ return () => { controller.abort(); }; - }, [canRender, workspace]); + }, [isOpen, workspace]); - if (!canRender || !workspace) { + if (!canShowPopup || !workspace) { return null; } + const handleClose = () => { + if (isNew) dismiss(); + onManuallyClose?.(); + }; + const deepCopyUrl = `${typeof window !== "undefined" ? window.location.origin : ""}/share-copy/${workspace.id}`; const activeUrl = linkMode === "collaborate" ? shareLinkUrl : deepCopyUrl; const isActiveLoading = linkMode === "collaborate" && isLoadingShareLink; @@ -106,9 +118,9 @@ export function RafflePopup({ return ( { - if (!next) dismiss(); + if (!next) handleClose(); }} > @@ -199,7 +211,7 @@ export function RafflePopup({ type="button" variant="outline" onClick={() => { - dismiss(); + handleClose(); onOpenFullShare(); }} > @@ -209,7 +221,7 @@ export function RafflePopup({ ) : ( )} - diff --git a/src/components/workspace-canvas/WorkspaceHeader.tsx b/src/components/workspace-canvas/WorkspaceHeader.tsx index 9eaede81..c481fae6 100644 --- a/src/components/workspace-canvas/WorkspaceHeader.tsx +++ b/src/components/workspace-canvas/WorkspaceHeader.tsx @@ -255,6 +255,8 @@ interface WorkspaceHeaderProps { // Workspace actions onOpenSettings?: () => void; onOpenShare?: () => void; + /** Open the raffle details popup (reopens the "Win a $50 Amazon gift card" dialog). */ + onShowRaffleDetails?: () => void; /** Item shown in the fullscreen workspace viewer (`openMode === "single"`) — breadcrumbs + header actions */ activeOpenWorkspaceItem?: Item | null; @@ -286,6 +288,7 @@ export function WorkspaceHeader({ onRenameFolder, onOpenSettings, onOpenShare, + onShowRaffleDetails, activeOpenWorkspaceItem = null, onCloseActiveItem, @@ -1240,10 +1243,10 @@ export function WorkspaceHeader({ Feedback - {isWorkspaceOwner && currentWorkspaceId && onOpenShare && ( + {isWorkspaceOwner && currentWorkspaceId && ( )} {onOpenShare && (