Skip to content

Commit 43c7f98

Browse files
committed
feat: enhance HackathonPage with published modal and session storage
- Added a modal to display published hackathon details upon successful publication. - Implemented session storage to retain published hackathon data for user experience. - Refactored state management to handle modal visibility and data retrieval. - Improved loading and error handling in the HackathonPage component.
1 parent cadf9bf commit 43c7f98

23 files changed

Lines changed: 307 additions & 290 deletions

File tree

app/(landing)/organizations/[id]/hackathons/[hackathonId]/page.tsx

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,29 @@ import {
99
Check,
1010
} from 'lucide-react';
1111
import { useHackathons } from '@/hooks/use-hackathons';
12-
import { useEffect } from 'react';
12+
import { useEffect, useState } from 'react';
1313
import { useHackathonAnalytics } from '@/hooks/use-hackathon-analytics';
1414
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
1515
import { HackathonStatistics } from '@/components/organization/hackathons/details/HackathonStatistics';
1616
import { HackathonCharts } from '@/components/organization/hackathons/details/HackathonCharts';
1717
import { HackathonTimeline } from '@/components/organization/hackathons/details/HackathonTimeline';
1818
import { AuthGuard } from '@/components/auth';
1919
import Loading from '@/components/Loading';
20+
import HackathonPublishedModal from '@/components/organization/hackathons/new/tabs/components/review/HackathonPublishedModal';
21+
import type { PublishResponseData } from '@/hooks/use-hackathon-publish';
22+
23+
const STORAGE_KEY = 'boundless_hackathon_published';
2024

2125
export default function HackathonPage() {
2226
const params = useParams();
2327
const organizationId = params.id as string;
2428
const hackathonId = params.hackathonId as string;
2529

30+
const [publishedModalData, setPublishedModalData] = useState<{
31+
publishResponse: PublishResponseData;
32+
organizationId: string;
33+
} | null>(null);
34+
2635
const { currentHackathon, currentLoading, currentError, fetchHackathon } =
2736
useHackathons({
2837
organizationId,
@@ -41,6 +50,37 @@ export default function HackathonPage() {
4150
}
4251
}, [organizationId, hackathonId, fetchHackathon]);
4352

53+
useEffect(() => {
54+
try {
55+
const raw = sessionStorage.getItem(STORAGE_KEY);
56+
if (!raw) return;
57+
const payload = JSON.parse(raw) as {
58+
organizationId: string;
59+
id: string;
60+
slug: string;
61+
publishedAt: string;
62+
message: string;
63+
escrowAddress: string;
64+
transactionHash: string | null;
65+
};
66+
if (payload.id !== hackathonId) return;
67+
sessionStorage.removeItem(STORAGE_KEY);
68+
setPublishedModalData({
69+
publishResponse: {
70+
id: payload.id,
71+
slug: payload.slug,
72+
publishedAt: payload.publishedAt,
73+
message: payload.message,
74+
escrowAddress: payload.escrowAddress,
75+
transactionHash: payload.transactionHash,
76+
},
77+
organizationId: payload.organizationId,
78+
});
79+
} catch {
80+
// ignore
81+
}
82+
}, [hackathonId]);
83+
4484
if (currentLoading) {
4585
return (
4686
<div className='flex min-h-screen items-center justify-center bg-black'>
@@ -95,6 +135,15 @@ export default function HackathonPage() {
95135
return (
96136
<AuthGuard redirectTo='/auth?mode=signin' fallback={<Loading />}>
97137
<div className='min-h-screen bg-black'>
138+
<HackathonPublishedModal
139+
open={!!publishedModalData}
140+
onOpenChange={open => {
141+
if (!open) setPublishedModalData(null);
142+
}}
143+
publishResponse={publishedModalData?.publishResponse ?? null}
144+
organizationId={publishedModalData?.organizationId}
145+
/>
146+
98147
{/* Hero Section with Hackathon Name */}
99148
<div className='border-b border-gray-900 p-4'>
100149
<div className='mx-auto max-w-7xl'>

app/(landing)/projects/[slug]/page.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,18 @@ function ProjectContent({
7979
setLoading(true);
8080
setError(null);
8181

82-
// If query param specifies submission, try that first/only
8382
if (isSubmission) {
8483
await fetchSubmission(id);
8584
return;
8685
}
8786

88-
// Try fetching as crowdfunding project first
8987
try {
9088
const projectData = await getCrowdfundingProject(id);
9189
if (projectData) {
9290
setProject(projectData);
9391
return;
9492
}
9593
} catch (e) {
96-
// Ignore error and try fetching as submission
97-
console.log('Not a crowdfunding project, checking submission...', e);
98-
// Fallback to submission check
9994
await fetchSubmission(id);
10095
}
10196
} catch {

app/me/crowdfunding/[slug]/milestones/[milestoneIndex]/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ export default function MilestoneDetailPage({ params }: PageProps) {
258258
</div>
259259
);
260260
}
261-
console.log(milestone.orderIndex);
262261
return (
263262
<div className='px-6 py-8'>
264263
<MilestoneDetailHeader

components/auth/login-form.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ export function LoginForm({ onSuccess, onError }: LoginFormProps) {
3636
const onSubmit = async (data: LoginFormData) => {
3737
try {
3838
setIsLoading(true);
39-
// console.log('Attempting login for:', data.email);
4039

4140
const { error } = await authClient.signIn.email(
4241
{
@@ -46,7 +45,6 @@ export function LoginForm({ onSuccess, onError }: LoginFormProps) {
4645
},
4746
{
4847
onSuccess: () => {
49-
// console.log('Login successful');
5048
toast.success('Login successful!');
5149
onSuccess?.();
5250
},

components/hackathons/HackathonsPage.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ const HackathonsPage: React.FC<HackathonsPageProps> = ({ className } = {}) => {
3838
totalCount,
3939
loadMore,
4040
} = useHackathonsList({ initialFilters: filters });
41-
// const { transformHackathonForCard } = useHackathonTransform();
42-
console.log(hackathons);
4341
const hackathonCards = React.useMemo(() => {
4442
return hackathons.map(hackathon => {
4543
return (

components/hackathons/participants/profileCard.tsx

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,6 @@ export function ProfileCard({ participant, onInviteClick }: ProfileCardProps) {
117117
// Check if current user can invite this participant
118118
const canInvite = useMemo(() => {
119119
if (!user || !currentUserParticipant || !currentHackathon) {
120-
console.log('[DEBUG] canInvite: missing prerequisites', {
121-
user: !!user,
122-
currentUserParticipant: !!currentUserParticipant,
123-
currentHackathon: !!currentHackathon,
124-
});
125120
return false;
126121
}
127122

@@ -151,15 +146,6 @@ export function ProfileCard({ participant, onInviteClick }: ProfileCardProps) {
151146

152147
const isLeader = isEnrichedLeader || isDirectLeader;
153148

154-
console.log('[DEBUG] ProfileCard canInvite check:', {
155-
target: participant.username,
156-
isLeader,
157-
isEnrichedLeader,
158-
isDirectLeader,
159-
currentUserRole: currentUserParticipant.role,
160-
currentUserId,
161-
});
162-
163149
return isLeader;
164150
}, [user, currentUserParticipant, participant, currentHackathon, teams]);
165151

components/hackathons/submissions/submissionTab.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ const SubmissionTabContent: React.FC<SubmissionTabContentProps> = ({
8181
setSelectedSort,
8282
setSelectedCategory,
8383
} = useSubmissions();
84-
console.log({ submissions });
8584
const { currentHackathon } = useHackathonData();
8685
const { status } = useHackathonStatus(
8786
currentHackathon?.startDate,

components/hackathons/team-formation/MyInvitationsList.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ export function MyInvitationsList({ hackathonId }: MyInvitationsListProps) {
7474
teamId: teamId || '',
7575
autoFetch: !!teamId && isLeader,
7676
});
77-
console.log(receivedInvitations, sentInvitations);
7877

7978
const isLoading =
8079
activeTab === 'received' ? isLoadingReceived : isLoadingSent;

components/organization/hackathons/new/NewHackathonTab.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ export default function NewHackathonTab({
8282
// Define the callback after hooks are initialized
8383
const onDraftLoaded = useCallback(
8484
(formData: any, firstIncompleteStep: StepKey) => {
85-
console.log('sjcdkformData', formData);
8685
setStepData(formData);
8786
setActiveTab(firstIncompleteStep);
8887

@@ -323,7 +322,6 @@ export default function NewHackathonTab({
323322
isSavingDraft={isSavingDraft}
324323
organizationId={derivedOrgId}
325324
draftId={draftId}
326-
publishResponse={publishResponse}
327325
/>
328326
</TabsContent>
329327
</div>

components/organization/hackathons/new/tabs/ReviewTab.tsx

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
AccordionTrigger,
1414
} from '@/components/ui/accordion';
1515
import DraftSavedModal from './components/review/DraftSavedModal';
16-
import HackathonPublishedModal from './components/review/HackathonPublishedModal';
1716
import { ReviewHeader } from './components/review/ReviewHeader';
1817
import { EscrowSummary } from './components/review/EscrowSummary';
1918
import { WalletConnectionWarning } from './components/review/WalletConnectionWarning';
@@ -22,7 +21,6 @@ import { SectionRenderer } from './components/review/SectionRenderer';
2221
import { usePrizePoolCalculations } from '@/hooks/use-prize-pool-calculations';
2322
import { REVIEW_SECTION_CONFIG } from './constants/review-sections';
2423
import { toast } from 'sonner';
25-
import type { PublishResponseData } from '@/hooks/use-hackathon-publish';
2624

2725
interface ReviewTabProps {
2826
allData: {
@@ -40,7 +38,6 @@ interface ReviewTabProps {
4038
isSavingDraft?: boolean;
4139
organizationId?: string;
4240
draftId?: string | null;
43-
publishResponse?: PublishResponseData | null;
4441
}
4542

4643
export default function ReviewTab({
@@ -52,22 +49,13 @@ export default function ReviewTab({
5249
isSavingDraft = false,
5350
organizationId,
5451
draftId,
55-
publishResponse,
5652
}: ReviewTabProps) {
5753
const [showDraftModal, setShowDraftModal] = useState(false);
58-
const [showPublishedModal, setShowPublishedModal] = useState(false);
5954
const { walletAddress } = useWalletContext();
6055

6156
const { totalPrizePool, platformFee, totalFunding } =
6257
usePrizePoolCalculations(allData.rewards);
6358

64-
// Show published modal only when we have a successful publish response
65-
useEffect(() => {
66-
if (publishResponse) {
67-
setShowPublishedModal(true);
68-
}
69-
}, [publishResponse]);
70-
7159
const handlePublish = async () => {
7260
try {
7361
if (onPublish) {
@@ -158,13 +146,6 @@ export default function ReviewTab({
158146
// User can continue editing - modal will close
159147
}}
160148
/>
161-
162-
<HackathonPublishedModal
163-
open={showPublishedModal}
164-
onOpenChange={setShowPublishedModal}
165-
publishResponse={publishResponse}
166-
organizationId={organizationId}
167-
/>
168149
</div>
169150
);
170151
}

0 commit comments

Comments
 (0)