-
Notifications
You must be signed in to change notification settings - Fork 88
Feat/new hackathon layout #486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
0xdevcollins
wants to merge
4
commits into
main
Choose a base branch
from
feat/new-hackathon-layout
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+6,552
−1,288
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
9dc0742
feat: Implement comprehensive hackathon detail page with new header, …
0xdevcollins f22f059
fix: merge github.com:boundlessfi/boundless into feat/new-hackathon-l…
0xdevcollins 0730da5
fix: update coderabit
0xdevcollins 00b1dcf
feat: Enhance hackathon team invitation flow, recruitment post manage…
0xdevcollins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import Image from 'next/image'; | ||
| import React from 'react'; | ||
|
|
||
| const Banner = ({ banner, title }: { banner: string; title?: string }) => { | ||
| return ( | ||
| <div className='relative h-[200px] w-full bg-gray-200 md:h-[360px]'> | ||
| <Image | ||
| src={banner} | ||
| alt={`${title || 'hackathon'} banner`} | ||
| fill | ||
| className='object-cover' | ||
| priority | ||
| /> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default Banner; |
126 changes: 126 additions & 0 deletions
126
app/(landing)/hackathons/[slug]/components/header/ActionButtons.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| 'use client'; | ||
|
|
||
| import { useParams, useRouter } from 'next/navigation'; | ||
| import { BoundlessButton } from '@/components/buttons'; | ||
| import { IconUsers, IconUserPlus, IconLogout } from '@tabler/icons-react'; | ||
| import { | ||
| useHackathon, | ||
| useMyTeam, | ||
| useJoinHackathon, | ||
| useLeaveHackathon, | ||
| } from '@/hooks/hackathon/use-hackathon-queries'; | ||
| import { useHackathonData } from '@/lib/providers/hackathonProvider'; | ||
| import { useAuth } from '@/hooks/use-auth'; | ||
| import SharePopover from '@/components/common/SharePopover'; | ||
| import { toast } from 'sonner'; | ||
|
|
||
| const ActionButtons = () => { | ||
| const { slug } = useParams<{ slug: string }>(); | ||
| const router = useRouter(); | ||
| const { user } = useAuth(); | ||
| const { currentHackathon: hackathon, refreshCurrentHackathon } = | ||
| useHackathonData(); | ||
| const { data: myTeam } = useMyTeam(slug); | ||
|
|
||
| const joinMutation = useJoinHackathon(slug); | ||
| const leaveMutation = useLeaveHackathon(slug); | ||
|
|
||
| const isParticipant = user | ||
| ? !!hackathon?.isParticipant || | ||
| (hackathon?.participants || []).some((p: any) => p.userId === user.id) | ||
| : false; | ||
|
|
||
| const handleJoin = async () => { | ||
| try { | ||
| await joinMutation.mutateAsync(); | ||
| await refreshCurrentHackathon(); | ||
| toast.success('Successfully joined the hackathon!'); | ||
| } catch (error: any) { | ||
| toast.error(error.message || 'Failed to join hackathon'); | ||
| } | ||
| }; | ||
|
|
||
| const handleLeave = async () => { | ||
| try { | ||
| await leaveMutation.mutateAsync(); | ||
| toast.success('You have left the hackathon'); | ||
| } catch (error: any) { | ||
| toast.error(error.message || 'Failed to leave hackathon'); | ||
| } | ||
|
Comment on lines
+43
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refresh the seeded hackathon state after leaving.
Suggested fix const handleLeave = async () => {
try {
await leaveMutation.mutateAsync();
+ await refreshCurrentHackathon();
toast.success('You have left the hackathon');
} catch (error: any) {
toast.error(error.message || 'Failed to leave hackathon');
}
};🤖 Prompt for AI Agents |
||
| }; | ||
|
|
||
| const handleTabChange = (tab: string) => { | ||
| const searchParams = new URLSearchParams(window.location.search); | ||
| searchParams.set('tab', tab); | ||
| router.push(`?${searchParams.toString()}`); | ||
|
|
||
| const tabsElement = document.getElementById('hackathon-tabs'); | ||
| if (tabsElement) { | ||
| tabsElement.scrollIntoView({ behavior: 'smooth' }); | ||
| } | ||
| }; | ||
|
|
||
| const isRegistrationClosed = | ||
| hackathon?.registrationOpen === false || | ||
| (hackathon?.registrationDeadline && | ||
| new Date(hackathon.registrationDeadline) < new Date()) || | ||
| ['JUDGING', 'COMPLETED', 'ARCHIVED', 'CANCELLED'].includes( | ||
| hackathon?.status || '' | ||
| ); | ||
|
|
||
| const isIndividualOnly = hackathon?.participantType === 'INDIVIDUAL'; | ||
|
|
||
| return ( | ||
| <div className='flex w-full flex-col gap-3 md:w-auto md:flex-row md:items-center'> | ||
| {!isParticipant ? ( | ||
| <BoundlessButton | ||
| className='s d h-12 w-full rounded-xl bg-[#A7F950] px-8 font-bold text-black hover:bg-[#A7F950]/90 disabled:bg-white/5 disabled:text-white/20 md:w-auto' | ||
| icon={!isRegistrationClosed && <IconUserPlus size={20} />} | ||
| onClick={handleJoin} | ||
| loading={joinMutation.isPending} | ||
| disabled={isRegistrationClosed} | ||
| > | ||
| {isRegistrationClosed ? 'REGISTRATION CLOSED' : 'JOIN HACKATHON'} | ||
| </BoundlessButton> | ||
| ) : ( | ||
| <div className='flex w-full items-center gap-2 md:w-auto'> | ||
| <BoundlessButton | ||
| variant='outline' | ||
| className='h-12 flex-1 rounded-xl border-[#A7F950]/20 bg-[#232B20]/40 px-8 font-black text-[#A7F950] md:flex-none' | ||
| disabled | ||
| > | ||
| REGISTERED | ||
| </BoundlessButton> | ||
| <BoundlessButton | ||
| variant='outline' | ||
| size='icon' | ||
| className='h-12 w-12 shrink-0 rounded-xl border-red-500/20 bg-red-500/5 text-red-500 hover:border-red-500/30 hover:bg-red-500/10' | ||
| onClick={handleLeave} | ||
| loading={leaveMutation.isPending} | ||
| title='Leave Hackathon' | ||
| > | ||
| <IconLogout size={20} /> | ||
| </BoundlessButton> | ||
| </div> | ||
| )} | ||
|
|
||
| <div className='flex w-full gap-3 md:w-auto'> | ||
| {!isIndividualOnly && ( | ||
| <BoundlessButton | ||
| variant='outline' | ||
| fullWidth | ||
| className='h-12 flex-1 rounded-xl border-white/10 bg-white/5 px-6 font-black transition-all hover:border-white/20 hover:bg-white/10' | ||
| onClick={() => handleTabChange('team-formation')} | ||
| icon={<IconUsers size={20} />} | ||
| > | ||
| {myTeam ? 'MY TEAM' : 'FIND TEAM'} | ||
| </BoundlessButton> | ||
| )} | ||
|
|
||
| <SharePopover title={hackathon?.name} className='relative shrink-0' /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default ActionButtons; | ||
20 changes: 20 additions & 0 deletions
20
app/(landing)/hackathons/[slug]/components/header/Logo.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import React from 'react'; | ||
| import Image from 'next/image'; | ||
|
|
||
| const Logo = ({ logo, title }: { logo: string; title: string }) => { | ||
| return ( | ||
| <div className='flex h-20 w-20 shrink-0 items-center justify-center overflow-hidden rounded-2xl bg-[#111111]'> | ||
| {logo ? ( | ||
| <Image | ||
| src={logo} | ||
| alt={title || 'Logo'} | ||
| width={80} | ||
| height={80} | ||
| className='h-full w-full object-cover' | ||
| /> | ||
| ) : null} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default Logo; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 134
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 5311
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 190
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 132
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 1356
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 92
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 853
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 92
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 648
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 4819
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 6418
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 381
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 4678
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 4067
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 805
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 11796
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 320
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 4678
🏁 Script executed:
Repository: boundlessfi/boundless
Length of output: 5805
Replace
anytype and refresh state after leaving hackathon.The
participantsarray is already typed in the sharedParticipantmodel —anyjust hides payload drift. Additionally, thehandleLeavemutation should refresh the current hackathon likehandleJoindoes to keep the header state in sync with the backend.Suggested fix
const isParticipant = user ? !!hackathon?.isParticipant || - (hackathon?.participants || []).some((p: any) => p.userId === user.id) + (hackathon?.participants ?? []).some((p: Participant) => p.userId === user.id) : false;const handleLeave = async () => { try { await leaveMutation.mutateAsync(); + await refreshCurrentHackathon(); toast.success('You have left the hackathon'); } catch (error: any) { toast.error(error.message || 'Failed to leave hackathon'); } };Import
Participantfrom@/types/hackathonif not already imported.As per coding guidelines: "Do not use 'any' type; always search for proper Trustless Work entity types".
🤖 Prompt for AI Agents