Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/(landing)/hackathons/[slug]/HackathonPageClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ export default function HackathonPageClient() {
// Shared props for banner and sticky card
const sharedActionProps = {
deadline: currentHackathon.submissionDeadline,
submissionDeadlineExtendedAt: currentHackathon.submissionDeadlineExtendedAt,
startDate: currentHackathon.startDate,
totalPrizePool: currentHackathon.prizeTiers
.reduce((acc, prize) => acc + Number(prize.prizeAmount || 0), 0)
Expand Down
2 changes: 2 additions & 0 deletions app/(landing)/hackathons/[slug]/hackathon-detail-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ https://www.figma.com/design/EMNGAQl1SGObXcsoa24krt/Boundless_Project-Details?no
This design proposes a cleaner and more professional UI/UX for the hackathon detail page.

Included in the Figma file:

- Desktop layout
- Mobile layout
- Banner / hero placement proposal
Expand All @@ -23,6 +24,7 @@ The hackathon banner is placed as a full-width hero image at the top of the page
The sidebar becomes a compact summary card with key information and actions.

Design Goals

- Simpler UI and improved visual hierarchy
- Clear primary actions (Join, Submit, View Submission)
- Consistent spacing and typography
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const ParticipantsPage: React.FC = () => {
const hackathonId = params.hackathonId as string;

const [view, setView] = useState<'table' | 'grid'>('table');
const [pageSize, setPageSize] = useState(PAGE_SIZE);
const [filters, setFilters] = useState<FilterState>({
search: '',
status: 'all',
Expand All @@ -63,9 +64,9 @@ const ParticipantsPage: React.FC = () => {
() => ({
organizationId,
autoFetch: false,
pageSize: PAGE_SIZE, // Grid looks better with multiples of 3/4
pageSize, // Use dynamic page size
}),
[organizationId]
[organizationId, pageSize]
);

const {
Expand Down Expand Up @@ -110,7 +111,7 @@ const ParticipantsPage: React.FC = () => {
fetchParticipants(
actualHackathonId,
1,
PAGE_SIZE,
pageSize,
mapFiltersToParams(filters, debouncedSearch)
);
}
Expand All @@ -120,6 +121,7 @@ const ParticipantsPage: React.FC = () => {
debouncedSearch,
filters.status,
filters.type,
pageSize,
]);

// Statistics
Expand Down Expand Up @@ -161,12 +163,12 @@ const ParticipantsPage: React.FC = () => {
}, [organizationId, actualHackathonId]);

// Handlers
const handlePageChange = (page: number) => {
const handlePageChange = (page: number, limit?: number) => {
if (actualHackathonId) {
fetchParticipants(
actualHackathonId,
page,
PAGE_SIZE,
limit ?? pageSize,
mapFiltersToParams(filters, debouncedSearch)
);
}
Expand Down Expand Up @@ -220,7 +222,7 @@ const ParticipantsPage: React.FC = () => {
fetchParticipants(
actualHackathonId,
participantsPagination.currentPage,
PAGE_SIZE,
pageSize,
mapFiltersToParams(filters, debouncedSearch)
);
}
Expand All @@ -241,16 +243,17 @@ const ParticipantsPage: React.FC = () => {
},
onPaginationChange: updater => {
if (typeof updater === 'function') {
const newState = (
updater as (old: { pageIndex: number; pageSize: number }) => {
pageIndex: number;
pageSize: number;
}
)({
const newState = updater({
pageIndex: participantsPagination.currentPage - 1,
pageSize: participantsPagination.itemsPerPage,
});
handlePageChange(newState.pageIndex + 1);

if (newState.pageSize !== participantsPagination.itemsPerPage) {
setPageSize(newState.pageSize);
handlePageChange(1, newState.pageSize);
} else {
handlePageChange(newState.pageIndex + 1);
}
}
},
});
Expand Down
225 changes: 0 additions & 225 deletions app/dashboard/page copy.tsx

This file was deleted.

6 changes: 0 additions & 6 deletions app/dashboard/page.tsx

This file was deleted.

25 changes: 25 additions & 0 deletions app/me/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ interface MeLayoutProfile {
image?: string;
joinedHackathons?: ProfileItemWithId[];
hackathonSubmissionsAsParticipant?: ProfileItemWithId[];
projects?: ProfileItemWithId[];
};
image?: string;
hackathonSubmissionsAsParticipant?: ProfileItemWithId[];
projects?: ProfileItemWithId[];
stats?: {
projectsCreated?: number;
};
}

const getId = (item: ProfileItemWithId): string | undefined =>
Expand Down Expand Up @@ -69,6 +74,25 @@ const MeLayout = ({ children }: MeLayoutProps): React.ReactElement => {
}).length;
}, [typedProfile]);

const projectsCount = useMemo(() => {
if (!typedProfile) return 0;
// stats.projectsCreated is often the most direct count
if (typeof typedProfile.stats?.projectsCreated === 'number') {
return typedProfile.stats.projectsCreated;
}
// Fallback to array lengths
const fromUser = typedProfile.user?.projects ?? [];
const fromProfile = typedProfile.projects ?? [];
const merged = [...fromUser, ...fromProfile];
const seen = new Set<string>();
return merged.filter(p => {
const id = getId(p);
if (!id || seen.has(id)) return false;
seen.add(id);
return true;
}).length;
}, [typedProfile]);

// Only show full-screen spinner on first load, not on background refetches
if (isLoading && !hasLoadedOnce.current) {
return (
Expand All @@ -92,6 +116,7 @@ const MeLayout = ({ children }: MeLayoutProps): React.ReactElement => {
counts={{
participating: hackathonsCount,
submissions: submissionsCount,
projects: projectsCount,
}}
variant='inset'
/>
Expand Down
Loading