Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
28c3fd5
fix: fix hero svg
Benjtalkshow Sep 27, 2025
0958765
Merge branch 'main' of https://github.com/Benjtalkshow/boundless
Benjtalkshow Sep 27, 2025
520594c
fix: fix landing footer
Benjtalkshow Sep 30, 2025
a1521a5
fix: revert backed by component
Benjtalkshow Sep 30, 2025
f968b88
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 3, 2025
c2c5d22
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 3, 2025
b862d17
fix: modify md editor
Benjtalkshow Oct 7, 2025
dbc2807
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 7, 2025
d0c05ba
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 7, 2025
ac7c0f9
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 7, 2025
0fc910c
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 9, 2025
f594e5d
fix: make projects page server components
Benjtalkshow Oct 10, 2025
a6a4f34
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 10, 2025
f12775b
fix: refactor project details page
Benjtalkshow Oct 10, 2025
2a37a09
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 10, 2025
896e7b4
feat: implement organization page
Benjtalkshow Oct 11, 2025
b605752
Merge branch 'main' of https://github.com/Benjtalkshow/boundless into…
Benjtalkshow Oct 11, 2025
38de515
fix: initialize organization settings
Benjtalkshow Oct 11, 2025
dacf99c
fix: modify organization page
Benjtalkshow Oct 11, 2025
cbab31c
fix: minor fixes
Benjtalkshow Oct 12, 2025
3b6c597
fix: minor fixes
Benjtalkshow Oct 12, 2025
a007977
fix: fix conflict
Benjtalkshow Oct 12, 2025
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
2 changes: 1 addition & 1 deletion app/(landing)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface LandingLayoutProps {

export default function LandingLayout({ children }: LandingLayoutProps) {
return (
<div className='bg-background relative flex min-h-screen flex-col pt-5 md:pt-11'>
<div className='bg-background relative flex min-h-screen flex-col'>
<Navbar />
<main className='flex-1'>{children}</main>
<Footer />
Expand Down
23 changes: 23 additions & 0 deletions app/(landing)/organizations/[id]/grants/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import { useParams } from 'next/navigation';
import OrganizationHeader from '@/components/organization/OrganizationHeader';
import OrganizationSidebar from '@/components/organization/OrganizationSidebar';

export default function GrantsPage() {
const params = useParams();
const organizationId = params.id as string;

return (
<div className='min-h-screen bg-black text-white'>
<OrganizationHeader />
<div className='flex'>
<OrganizationSidebar organizationId={organizationId} />
<main className='flex-1 p-8'>
<h1 className='text-2xl font-bold'>Grants</h1>
<p className='mt-2 text-zinc-400'>Manage your grants here</p>
</main>
</div>
</div>
);
}
23 changes: 23 additions & 0 deletions app/(landing)/organizations/[id]/hackathons/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import { useParams } from 'next/navigation';
import OrganizationHeader from '@/components/organization/OrganizationHeader';
import OrganizationSidebar from '@/components/organization/OrganizationSidebar';

export default function HackathonsPage() {
const params = useParams();
const organizationId = params.id as string;

return (
<div className='min-h-screen bg-black text-white'>
<OrganizationHeader />
<div className='flex'>
<OrganizationSidebar organizationId={organizationId} />
<main className='flex-1 p-8'>
<h1 className='text-2xl font-bold'>Hackathons</h1>
<p className='mt-2 text-zinc-400'>Manage your hackathons here</p>
</main>
</div>
</div>
);
}
32 changes: 32 additions & 0 deletions app/(landing)/organizations/[id]/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use client';

import { useParams } from 'next/navigation';
import OrganizationHeader from '@/components/organization/OrganizationHeader';
import OrganizationSidebar from '@/components/organization/OrganizationSidebar';
import OrganizationSettings from '@/components/organization/OrganizationSettings';

export default function OrganizationSettingsPage() {
const params = useParams();
const organizationId = params.id as string;

// TODO: Fetch organization data based on ID
const mockOrgData = {
name: 'Tech Innovators Hub',
logo: '/tech-company-logo.jpg',
tagline: 'Building the future of technology',
about: 'We are a community of innovators...',
};

return (
<div className='min-h-screen bg-black text-white'>
<OrganizationHeader />
<div className='flex'>
<OrganizationSidebar organizationId={organizationId} />
<OrganizationSettings
organizationId={organizationId}
initialData={mockOrgData}
/>
</div>
</div>
);
}
33 changes: 33 additions & 0 deletions app/(landing)/organizations/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use client';

import type React from 'react';

import OrganizationHeader from '@/components/organization/OrganizationHeader';
import OrganizationSidebar from '@/components/organization/OrganizationSidebar';
import { usePathname } from 'next/navigation';

export default function OrganizationsLayout({
children,
}: {
children: React.ReactNode;
}) {
const pathname = usePathname();

const showSidebar =
pathname.includes('/new') ||
(pathname.split('/').length > 4 && pathname !== '/dashboard/organizations');

return (
<div className='min-h-screen bg-black text-white'>
<OrganizationHeader />
{showSidebar ? (
<div className='flex border-t border-t-zinc-800'>
<OrganizationSidebar />
<main className='flex-1'>{children}</main>
</div>
) : (
<main>{children}</main>
)}
</div>
);
}
16 changes: 16 additions & 0 deletions app/(landing)/organizations/new/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use client';

import OrganizationSettings from '@/components/organization/OrganizationSettings';

export default function NewOrganizationPage() {
return (
<OrganizationSettings
initialData={{
name: 'Organization 1',
logo: '',
tagline: '',
about: '',
}}
/>
);
}
12 changes: 12 additions & 0 deletions app/(landing)/organizations/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import OrganizationPage from '@/components/organization/OrganizationPage';
import React from 'react';

const page = () => {
return (
<div>
<OrganizationPage />
</div>
);
};

export default page;
1 change: 1 addition & 0 deletions components/auth/OtpForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const OtpForm = ({
}

toast.success('Account created successfully!');
window.location.reload();
onOtpSuccess();
} else {
const error = await response.json();
Expand Down
4 changes: 3 additions & 1 deletion components/landing-page/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ScrollSmoother } from 'gsap/ScrollSmoother';
import Image from 'next/image';
import { BoundlessButton } from '@/components/buttons';
import LooperSVG from './LooperSVG';
import { useRouter } from 'next/navigation';

gsap.registerPlugin(ScrollTrigger, ScrollSmoother);

Expand All @@ -18,7 +19,7 @@ interface HeroProps {
export default function Hero({ className = '' }: HeroProps) {
const heroRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);

const router = useRouter();
const animationConfig = useMemo(
() => ({
ellipse: {
Expand Down Expand Up @@ -196,6 +197,7 @@ export default function Hero({ className = '' }: HeroProps) {
size='xl'
fullWidth
aria-label='Explore featured projects and campaigns'
onClick={() => router.push('/projects')}
>
Explore Projects
</BoundlessButton>
Expand Down
35 changes: 22 additions & 13 deletions components/landing-page/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useRef, useState } from 'react';
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
import { BoundlessButton } from '../buttons';
import { useRouter } from 'next/navigation';
import { usePathname, useRouter } from 'next/navigation';
import { Sheet, SheetTrigger, SheetContent, SheetClose } from '../ui/sheet';
import { useAuthStatus, useAuthActions } from '@/hooks/use-auth';
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
Expand Down Expand Up @@ -48,6 +48,8 @@ export function Navbar() {
const ctaRef = useRef<HTMLDivElement>(null);
const router = useRouter();
const { isAuthenticated, isLoading, user } = useAuthStatus();
const pathname = usePathname();

useGSAP(
() => {
gsap.fromTo(
Expand Down Expand Up @@ -154,6 +156,9 @@ export function Navbar() {
{ scope: navbarRef }
);

if (pathname.startsWith('/organizations')) {
return null;
}
return (
<nav
ref={navbarRef}
Expand Down Expand Up @@ -246,18 +251,22 @@ function AuthenticatedNav({
<Plus className='group-hover:text-primary h-4 w-4' />
</span>
</DropdownMenuItem>
<DropdownMenuItem className='group hover:text-primary px-6 py-3.5 text-white hover:!bg-transparent'>
<span className='group-hover:text-primary flex w-full items-center justify-between'>
Host Hackathon
<ArrowUpRight className='group-hover:text-primary h-4 w-4' />
</span>
</DropdownMenuItem>
<DropdownMenuItem className='group hover:text-primary px-6 py-3.5 text-white hover:!bg-transparent'>
<span className='group-hover:text-primary flex w-full items-center justify-between'>
Create Grant
<ArrowUpRight className='group-hover:text-primary h-4 w-4' />
</span>
</DropdownMenuItem>
<Link href='/organizations/new' target='_blank' rel='noreferrer'>
<DropdownMenuItem className='group hover:text-primary px-6 py-3.5 text-white hover:!bg-transparent'>
<span className='group-hover:text-primary flex w-full items-center justify-between'>
Host Hackathon
<ArrowUpRight className='group-hover:text-primary h-4 w-4' />
</span>
</DropdownMenuItem>
</Link>
<Link href='/organizations/new' target='_blank' rel='noreferrer'>
<DropdownMenuItem className='group hover:text-primary px-6 py-3.5 text-white hover:!bg-transparent'>
<span className='group-hover:text-primary flex w-full items-center justify-between'>
Create Grant
<ArrowUpRight className='group-hover:text-primary h-4 w-4' />
</span>
</DropdownMenuItem>
</Link>
</DropdownMenuContent>
</DropdownMenu>

Expand Down
105 changes: 105 additions & 0 deletions components/organization/OrganizationContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
'use client';
import { Search, ArrowUpDown, Plus } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import OrganizationCard from './cards/OrganzationCards';
import Link from 'next/link';

const mockOrganizations = [
{
id: '1',
name: 'Tech Innovators Hub',
logo: '/organization-logo.svg',
createdAt: '2 days ago',
hackathons: { count: 3, submissions: 1 },
grants: { count: 7, applications: 3 },
},
{
id: '2',
name: 'Green Energy Initiative',
logo: '/organization-logo.svg',
createdAt: '1 week ago',
hackathons: { count: 5, submissions: 2 },
grants: { count: 12, applications: 8 },
},
{
id: '3',
name: 'AI Research Collective',
logo: '/organization-logo.svg',
createdAt: '3 weeks ago',
hackathons: { count: 8, submissions: 5 },
grants: { count: 15, applications: 10 },
},
{
id: '4',
name: 'Community Builders Network',
logo: '/organization-logo.svg',
createdAt: '1 month ago',
hackathons: { count: 2, submissions: 0 },
grants: { count: 4, applications: 2 },
},
];

export default function OrganizationContent() {
const hasorganizations = mockOrganizations.length > 0;
return (
<main className=''>
{/* Search and Sort Bar */}
{hasorganizations && (
<section className='mb-8 hidden border-b border-b-zinc-800 px-8 md:block'>
<div className='mx-auto flex max-w-5xl items-center gap-4'>
<div className='relative flex-1'>
<Search className='absolute top-1/2 left-4 h-5 w-5 -translate-y-1/2 text-zinc-500' />
<Input
type='text'
placeholder='Search organization, hackathon, or grants'
className='w-full rounded-lg border-zinc-800 bg-zinc-900 py-6 pr-4 pl-12 text-white placeholder:text-zinc-500 focus-visible:border-lime-500 focus-visible:ring-[1px] focus-visible:ring-lime-500'
/>
</div>
<Button
variant='outline'
className='text- rounded-lg border-zinc-800 bg-black px-6 py-6 hover:bg-transparent hover:text-lime-500'
>
<ArrowUpDown className='h-4 w-4' />
Sort
</Button>
{hasorganizations && (
<div className='flex h-23 items-center border-l border-l-zinc-800 pl-4'>
<Link href='/organizations/new'>
<Button className='rounded-lg bg-[#a6f948] px-6 py-6 text-black hover:bg-lime-600'>
Add Organization
<Plus className='h-4 w-4' />
</Button>
</Link>
</div>
)}
</div>
</section>
)}

<section className='mx-auto max-w-5xl px-8 py-8 md:px-0'>
{/* Add Organization Section */}
{hasorganizations && (
<div className='grid grid-cols-1 gap-6'>
{mockOrganizations.map(org => (
<Link href={`/organization/${org.id}`} key={org.id}>
<OrganizationCard {...org} />
</Link>
))}
</div>
)}

{!hasorganizations && (
<div className='mx-8 flex items-center justify-center rounded-lg border-1 border-dashed border-green-600 p-32'>
<Link href='/organizations/new'>
<button className='flex items-center gap-2 font-medium text-lime-500 transition-colors hover:text-lime-400'>
<span>Add Organization</span>
<Plus className='h-5 w-5' size={100} />
</button>
</Link>
</div>
)}
</section>
</main>
);
}
Loading
Loading