Skip to content

Commit 74472e9

Browse files
committed
Merge branch 'main' of github.com:0xdevcollins/boundless into production
2 parents 0d1743e + 951d107 commit 74472e9

357 files changed

Lines changed: 358064 additions & 5575 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/rules/trustless-rule.mdc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
alwaysApply: true
3+
---
4+
You are a **Senior Front-End Developer** and **Expert** in:
5+
- ReactJS, NextJS, JavaScript, TypeScript
6+
- TailwindCSS, Shadcn, Radix UI
7+
- HTML, CSS, and modern UI/UX best practices
8+
9+
You are methodical, precise, and a master at reasoning through complex requirements. You always provide correct, DRY, bug-free, production-ready code.
10+
11+
## General Rules
12+
- Follow the user’s requirements **exactly** as stated.
13+
- Think step-by-step:
14+
1. **Analyze** the requirement.
15+
2. **Write detailed pseudocode** describing the implementation plan.
16+
3. **Confirm** the plan (if asked).
17+
4. **Write complete code** that matches the plan.
18+
- Never guess. If something is unclear, ask for clarification.
19+
- If an external library is mentioned, always refer to its official documentation before implementation.
20+
- Always ensure the final code is fully functional, with no placeholders, `TODO`s, or missing parts.
21+
- Prefer readability over performance.
22+
- Use best practices for React & Next.js development.
23+
- Do not use cd in order to access to determinate root, neither use &&, | or something like that in shell actions.
24+
- Do not verify the build during the Trustless Work implementations.
25+
- In each npm i, the name of the dependency must be enclosed in double quotation marks (“”).
26+
- Do not ask for 2 o more ways to implement, just do it the best way possible.
27+
- Do not plan or ask for steps; just implement the code without asking questions.
28+
29+
## Trustless Work Integration Context
30+
When working with Trustless Work:
31+
- Documentation (I'll provide you the docs in the cursor docs management):
32+
- React Library → <https://docs.trustlesswork.com/trustless-work/react-library>
33+
- Wallet Kit → <https://docs.trustlesswork.com/trustless-work/developer-resources/stellar-wallet-kit-quick-integration>
34+
- Types → <https://docs.trustlesswork.com/trustless-work/developer-resources/types>
35+
- Ensure proper installation and configuration before usage.
36+
- Use provided Types from the documentation when applicable.
37+
- Follow the API and component usage exactly as described in the docs.
38+
- Do not use any, instead always you must search for the Trustless Work entities.
39+
40+
## Code Implementation Guidelines
41+
- Use **TailwindCSS classes** for styling; avoid plain CSS.
42+
- For conditional classes, prefer `clsx` or similar helper functions over ternary operators in JSX.
43+
- Use **descriptive** variable, function, and component names.
44+
- Event handlers start with `handle` (e.g., `handleClick`, `handleSubmit`).
45+
- Prefer **const** arrow functions with explicit type annotations over `function` declarations.
46+
- Always include all necessary imports at the top.
47+
- Use early returns to improve code clarity.
48+
49+
## Verification Before Delivery
50+
Before finalizing:
51+
1. Check that all required imports are present.
52+
2. Ensure the code compiles in a Next.js 14+ environment.
53+
3. Confirm that Tailwind and Shadcn styles render correctly.
54+
4. Verify that Trustless Work components or hooks are properly initialized.
55+
5. Ensure TypeScript types are correct and there are no type errors.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ Before you begin, ensure you have the following installed:
208208
# Stellar Configuration
209209
NEXT_PUBLIC_STELLAR_NETWORK=testnet
210210
NEXT_PUBLIC_APP_URL=http://localhost:3000
211+
212+
# Trustless Work Configuration (optional)
213+
# Get your API key from: https://docs.trustlesswork.com
214+
NEXT_PUBLIC_TRUSTLESS_WORK_API_KEY=your-trustless-work-api-key
211215
```
212216

213217
6. **Run the development server:**

app/(landing)/bounties/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
import { Metadata } from 'next';
3+
import { generatePageMetadata } from '@/lib/metadata';
4+
5+
export const metadata: Metadata = generatePageMetadata('grants');
6+
7+
const GrantPage = () => {
8+
return (
9+
<div className='mx-auto mt-10 max-w-[1440px] px-5 py-5 text-center text-4xl font-bold text-white md:px-[50px] lg:px-[100px]'>
10+
Bounties Page
11+
</div>
12+
);
13+
};
14+
15+
export default GrantPage;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
'use client';
2+
3+
import { useState, useEffect, useMemo } from 'react';
4+
import { useRouter, useSearchParams, useParams } from 'next/navigation';
5+
import { useHackathonData } from '@/lib/providers/hackathonProvider';
6+
7+
import { HackathonBanner } from '@/components/hackathons/hackathonBanner';
8+
import { HackathonNavTabs } from '@/components/hackathons/hackathonNavTabs';
9+
import { HackathonOverview } from '@/components/hackathons/overview/hackathonOverview';
10+
import { HackathonParticipants } from '@/components/hackathons/participants/hackathonParticipant';
11+
import { HackathonResources } from '@/components/hackathons/resources/resources';
12+
import SubmissionTab from '@/components/hackathons/submissions/submissionTab';
13+
import { HackathonDiscussions } from '@/components/hackathons/discussion/comment';
14+
import LoadingScreen from '@/components/landing-page/project/CreateProjectModal/LoadingScreen';
15+
16+
export default function HackathonPage() {
17+
const router = useRouter();
18+
const searchParams = useSearchParams();
19+
const params = useParams();
20+
21+
const {
22+
currentHackathon,
23+
content,
24+
timelineEvents,
25+
participants,
26+
submissions,
27+
prizes,
28+
loading,
29+
setCurrentHackathon,
30+
} = useHackathonData();
31+
32+
const hackathonTabs = useMemo(
33+
() => [
34+
{ id: 'overview', label: 'Overview' },
35+
{ id: 'participants', label: 'Participants', badge: participants.length },
36+
{ id: 'resources', label: 'Resources' },
37+
{
38+
id: 'submission',
39+
label: 'Submissions',
40+
badge: submissions.filter(p => p.status === 'Approved').length,
41+
},
42+
{ id: 'discussions', label: 'Discussions' },
43+
],
44+
[participants.length, submissions]
45+
);
46+
47+
const hackathonId = params.slug as string;
48+
const [activeTab, setActiveTab] = useState('overview');
49+
50+
useEffect(() => {
51+
if (hackathonId) {
52+
setCurrentHackathon(hackathonId);
53+
}
54+
}, [hackathonId, setCurrentHackathon]);
55+
56+
useEffect(() => {
57+
const tabFromUrl = searchParams.get('tab');
58+
if (tabFromUrl && hackathonTabs.some(tab => tab.id === tabFromUrl)) {
59+
setActiveTab(tabFromUrl);
60+
}
61+
}, [searchParams, hackathonTabs]);
62+
63+
const handleTabChange = (tabId: string) => {
64+
setActiveTab(tabId);
65+
const params = new URLSearchParams(searchParams.toString());
66+
params.set('tab', tabId);
67+
router.push(`?${params.toString()}`, { scroll: false });
68+
};
69+
70+
if (loading) {
71+
return <LoadingScreen />;
72+
}
73+
74+
if (!currentHackathon) {
75+
return (
76+
<div className='flex min-h-screen items-center justify-center'>
77+
<div className='text-center'>
78+
<h1 className='mb-4 text-2xl font-bold text-white'>
79+
Hackathon not found
80+
</h1>
81+
<p className='text-gray-400'>
82+
The hackathon you're looking for doesn't exist.
83+
</p>
84+
</div>
85+
</div>
86+
);
87+
}
88+
89+
return (
90+
<div className='mx-auto mt-10 max-w-[1440px] px-5 py-5 text-center text-4xl font-bold text-white md:px-[50px] lg:px-[100px]'>
91+
{/* Banner */}
92+
<HackathonBanner
93+
title={currentHackathon.title}
94+
subtitle={currentHackathon.subtitle}
95+
deadline={currentHackathon.deadline}
96+
categories={currentHackathon.categories}
97+
status={currentHackathon.status}
98+
participants={currentHackathon.participants}
99+
totalPrizePool={currentHackathon.totalPrizePool}
100+
imageUrl={currentHackathon.imageUrl}
101+
startDate={currentHackathon.startDate} // if upcoming
102+
/>
103+
104+
{/* Tabs */}
105+
<HackathonNavTabs
106+
tabs={hackathonTabs}
107+
activeTab={activeTab}
108+
onTabChange={handleTabChange}
109+
/>
110+
111+
{/* Content */}
112+
<div className='mx-auto max-w-7xl px-6 py-12 text-white'>
113+
{activeTab === 'overview' && (
114+
<HackathonOverview
115+
content={content}
116+
timelineEvents={timelineEvents}
117+
prizes={prizes}
118+
/>
119+
)}
120+
121+
{activeTab === 'participants' && <HackathonParticipants />}
122+
123+
{activeTab === 'resources' && <HackathonResources />}
124+
125+
{activeTab === 'submission' && <SubmissionTab />}
126+
127+
{activeTab === 'discussions' && (
128+
<HackathonDiscussions hackathonId={hackathonId} />
129+
)}
130+
</div>
131+
</div>
132+
);
133+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { HackathonDataProvider } from '@/lib/providers/hackathonProvider';
2+
import { use } from 'react';
3+
4+
interface HackathonLayoutProps {
5+
children: React.ReactNode;
6+
params: Promise<{
7+
slug?: string;
8+
}>;
9+
}
10+
11+
export default function HackathonLayout({
12+
children,
13+
params,
14+
}: HackathonLayoutProps) {
15+
const resolvedParams = use(params);
16+
17+
return (
18+
<HackathonDataProvider hackathonSlug={resolvedParams.slug}>
19+
{children}
20+
</HackathonDataProvider>
21+
);
22+
}

app/(landing)/hackathons/page.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import React from 'react';
21
import { Metadata } from 'next';
32
import { generatePageMetadata } from '@/lib/metadata';
3+
import HackathonsPageHero from '@/components/hackathons/HackathonsPageHero';
4+
import HackathonsPage from '@/components/hackathons/HackathonsPage';
45

56
export const metadata: Metadata = generatePageMetadata('hackathons');
67

7-
const HackathonsPage = () => {
8+
export default function HackathonsPageRoute() {
89
return (
9-
<div className='mx-auto mt-10 max-w-[1440px] px-5 py-5 text-center text-4xl font-bold text-white md:px-[50px] lg:px-[100px]'>
10-
Hackathons Page
10+
<div className='relative mx-auto min-h-screen max-w-[1440px] px-5 py-5 md:px-[50px] lg:px-[100px]'>
11+
<HackathonsPageHero />
12+
<HackathonsPage />
1113
</div>
1214
);
13-
};
14-
15-
export default HackathonsPage;
15+
}

0 commit comments

Comments
 (0)