Skip to content

Commit 70fb1db

Browse files
committed
refactor: remove package-lock.json, update package.json dependencies, and add new components for expectations and voting interface
1 parent d1af155 commit 70fb1db

14 files changed

Lines changed: 3809 additions & 12486 deletions

File tree

package-lock.json

Lines changed: 0 additions & 11336 deletions
This file was deleted.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525
"@web3modal/wagmi": "^5.1.7",
2626
"class-variance-authority": "^0.7.0",
2727
"clsx": "^2.1.1",
28+
"date-fns": "^4.1.0",
2829
"next": "14.2.3",
2930
"react": "^18",
3031
"react-dom": "^18",
3132
"react-easy-emoji": "^1.8.1",
3233
"react-intersection-observer": "^9.13.0",
34+
"react-markdown": "^10.1.0",
3335
"react-responsive": "^10.0.0",
3436
"react-social-icons": "^6.18.0",
3537
"recharts": "^2.13.0",
38+
"remark-gfm": "^4.0.1",
3639
"starknet": "^7.6.2",
3740
"starknetkit": "^2.12.1",
3841
"tailwind-merge": "^2.3.0",

pnpm-lock.yaml

Lines changed: 2563 additions & 1150 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import { useParams } from 'next/navigation';
5+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6+
import { Button } from '@/components/ui/button';
7+
import { getMockExpectations, getMockMilestoneContent } from '@/lib/mock-api';
8+
import { fetchFromIPFS } from '@/lib/ipfs';
9+
import { Expectation, MilestoneContent } from '@/types/expectation';
10+
import VotingInterface from '@/components/VotingInterface';
11+
12+
import CountdownTimer from '@/components/CountdownTimer';
13+
import Link from 'next/link';
14+
import MarkdownRenderer from '@components/MarkdownRenderer';
15+
16+
export default function ExpectationPage() {
17+
const params = useParams();
18+
const uri = decodeURIComponent(params.uri as string);
19+
20+
const [expectation, setExpectation] = useState<Expectation | null>(null);
21+
const [milestoneContent, setMilestoneContent] = useState<MilestoneContent | null>(null);
22+
const [isLoading, setIsLoading] = useState(true);
23+
const [error, setError] = useState<string | null>(null);
24+
25+
useEffect(() => {
26+
const fetchData = async () => {
27+
try {
28+
setIsLoading(true);
29+
setError(null);
30+
31+
// Find expectation by milestoneURI
32+
const expectations = await getMockExpectations();
33+
const foundExpectation = expectations.find(exp => exp.milestoneURI === uri);
34+
35+
if (!foundExpectation) {
36+
setError('Expectation not found');
37+
return;
38+
}
39+
40+
setExpectation(foundExpectation);
41+
42+
// Try to fetch from IPFS first, then fallback to mock
43+
let content: MilestoneContent | null = null;
44+
45+
try {
46+
content = await fetchFromIPFS(uri);
47+
} catch (ipfsError) {
48+
console.warn('IPFS fetch failed, using mock data:', ipfsError);
49+
}
50+
51+
if (!content) {
52+
content = await getMockMilestoneContent(uri);
53+
}
54+
55+
if (!content) {
56+
setError('Failed to load milestone content');
57+
return;
58+
}
59+
60+
setMilestoneContent(content);
61+
} catch (err) {
62+
console.error('Error fetching expectation data:', err);
63+
setError('Failed to load expectation data');
64+
} finally {
65+
setIsLoading(false);
66+
}
67+
};
68+
69+
if (uri) {
70+
fetchData();
71+
}
72+
}, [uri]);
73+
74+
const handleVoteSubmitted = () => {
75+
// Refresh expectation data after vote
76+
if (expectation) {
77+
getMockExpectations().then(expectations => {
78+
const updatedExpectation = expectations.find(exp => exp.id === expectation.id);
79+
if (updatedExpectation) {
80+
setExpectation(updatedExpectation);
81+
}
82+
});
83+
}
84+
};
85+
86+
if (isLoading) {
87+
return (
88+
<main className="w-full h-full max-w-screen-2xl mx-auto">
89+
<div className="base:max-md:px-3 py-6 px-10">
90+
<div className="text-center py-20">
91+
<div className="text-ourWhite text-xl">Loading expectation...</div>
92+
</div>
93+
</div>
94+
</main>
95+
);
96+
}
97+
98+
if (error || !expectation || !milestoneContent) {
99+
return (
100+
<main className="w-full h-full max-w-screen-2xl mx-auto">
101+
<div className="base:max-md:px-3 py-6 px-10">
102+
<div className="text-center py-20">
103+
<div className="text-red-400 text-xl mb-4">
104+
{error || 'Expectation not found'}
105+
</div>
106+
<Link href="/dewhitepaper/expectations">
107+
<Button variant="outline" className="text-ourWhite px-8 rounded-none bg-[transparent] border-gray-600 font-extralight font-lighten tracking-widest hover:border-gray-500 transition-all duration-200 ease-in-out hover:scale-[1.02]">
108+
← Back to Expectations
109+
</Button>
110+
</Link>
111+
</div>
112+
</div>
113+
</main>
114+
);
115+
}
116+
117+
const isVotingActive = expectation.status === 'ongoing' && expectation.deadline > Date.now();
118+
119+
return (
120+
<main className="w-full h-full max-w-screen-2xl mx-auto">
121+
{/* Header */}
122+
<header className="py-2 h-fit base:max-md:px-3 px-10 items-center border-b border-gray-600 max-md:py-4 flex relative top-0 w-full">
123+
<div className="w-fit">
124+
<p className="bg-gradient-to-t mt-4 from-gray-400 mb-3 tab:text-8xl tracking-tighter text-4xl to-white bg-clip-text text-transparent font-bolden">
125+
EXPECTATION<span className="from-gray-400 tracking-tighter text-[10px] tab:text-[20px]">noun</span>
126+
</p>
127+
<div className="p-4">
128+
<div className="mx-auto px-6 relative h-fit min-h-32 border-l-gray-600 border-l-2 border-dashed">
129+
<div id="timeline-item" className="text-ourWhite flex mb-5">
130+
<span className="absolute flex items-center justify-center -left-[23px] bg-cover bg-block rounded w-10 h-10">
131+
1
132+
</span>
133+
<div className="relative top-[8px]">
134+
<dd className="poppins-regular">
135+
: a <strong className="poppins-extrabold">detailed proposal</strong> for community review and voting
136+
</dd>
137+
</div>
138+
</div>
139+
<div id="timeline-item" className="text-ourWhite flex">
140+
<span className="absolute flex items-center justify-center -left-[23px] bg-block bg-cover rounded w-10 h-10">
141+
2
142+
</span>
143+
<div className="relative top-[8px]">
144+
<dd className="poppins-regular">
145+
: a <strong className="poppins-extrabold">milestone commitment</strong> tied to treasury withdrawal requests
146+
</dd>
147+
</div>
148+
</div>
149+
</div>
150+
</div>
151+
</div>
152+
</header>
153+
154+
{/* Content */}
155+
<section className="base:max-md:px-3 py-6 px-10">
156+
<div className="mb-8">
157+
<div className="flex items-start justify-between mb-4">
158+
<div>
159+
<h1 className="tab:text-4xl text-2xl mb-2 tracking-wide font-bolden text-ourWhite">
160+
{milestoneContent.title}
161+
</h1>
162+
<div className="flex items-center gap-4 text-sm text-gray-400">
163+
<span className={`px-2 py-1 rounded ${
164+
expectation.status === 'ongoing' ? 'bg-yellow-900/20 text-yellow-400' :
165+
expectation.status === 'fulfilled' ? 'bg-green-900/20 text-green-400' :
166+
'bg-red-900/20 text-red-400'
167+
}`}>
168+
{expectation.status.toUpperCase()}
169+
</span>
170+
{isVotingActive && (
171+
<CountdownTimer deadline={expectation.deadline} />
172+
)}
173+
</div>
174+
</div>
175+
<Link href="/dewhitepaper/expectations">
176+
<Button variant="outline" size="sm" className="text-ourWhite px-6 rounded-none bg-[transparent] border-gray-600 font-extralight font-lighten tracking-widest hover:border-gray-500 transition-all duration-200 ease-in-out hover:scale-[1.02]">
177+
← Back to Expectations
178+
</Button>
179+
</Link>
180+
</div>
181+
</div>
182+
183+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
184+
{/* Main Content */}
185+
<div className="lg:col-span-2 space-y-6">
186+
{/* Proposal Content */}
187+
<Card className="bg-transparent text-white border-gray-600">
188+
<CardHeader>
189+
<CardTitle className="text-xl font-bolden text-ourWhite">
190+
Proposal Details
191+
</CardTitle>
192+
</CardHeader>
193+
<CardContent>
194+
<MarkdownRenderer content={milestoneContent.content} />
195+
</CardContent>
196+
</Card>
197+
198+
{/* GitHub Link */}
199+
<Card className="bg-transparent text-white border-gray-600">
200+
<CardHeader>
201+
<CardTitle className="text-lg font-bolden text-ourWhite">
202+
Full Proposal
203+
</CardTitle>
204+
</CardHeader>
205+
<CardContent>
206+
<p className="text-gray-300 poppins-regular mb-4">
207+
View the complete proposal on GitHub for more detailed information and technical specifications.
208+
</p>
209+
<a
210+
href={milestoneContent.bipLink}
211+
target="_blank"
212+
rel="noopener noreferrer"
213+
className="inline-flex items-center gap-2 text-blue-400 hover:text-blue-300 underline"
214+
>
215+
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
216+
<path fillRule="evenodd" d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z" clipRule="evenodd" />
217+
</svg>
218+
View on GitHub
219+
</a>
220+
</CardContent>
221+
</Card>
222+
</div>
223+
224+
{/* Voting Sidebar */}
225+
<div className="lg:col-span-1">
226+
<VotingInterface
227+
expectation={expectation}
228+
onVoteSubmitted={handleVoteSubmitted}
229+
/>
230+
</div>
231+
</div>
232+
</section>
233+
</main>
234+
);
235+
}

0 commit comments

Comments
 (0)