Skip to content

Commit e99384e

Browse files
feat: add testing setup with Jest and update project card component (boundlessfi#175)
- Add Jest, React Testing Library, and related dependencies - Configure Jest with TypeScript support - Add test setup files and sample test - Update project card component with new features Co-authored-by: Collins Ikechukwu <collinschristroa@gmail.com>
1 parent 2c5520c commit e99384e

6 files changed

Lines changed: 12833 additions & 9085 deletions

File tree

app/preview/page.tsx

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
'use client';
2+
import React from 'react';
3+
import ProjectCard from '@/components/ProjectCard';
4+
import { Project } from '@/types/project';
5+
6+
// Mock project data for preview
7+
const mockProjects: Project[] = [
8+
{
9+
id: '1',
10+
name: 'Bitmed',
11+
description:
12+
'To build a secure, transparent, and trusted digital health ecosystem powered by blockchain technology, enabling seamless data sharing and patient care coordination.',
13+
image: '/placeholder-image.jpg',
14+
link: '#',
15+
tags: ['healthcare', 'blockchain', 'digital-health'],
16+
category: 'Category',
17+
type: 'healthcare',
18+
amount: 50000,
19+
status: 'under_review',
20+
createdAt: '2024-01-01',
21+
updatedAt: '2024-01-01',
22+
owner: 'user123',
23+
ownerName: 'Creator Name',
24+
ownerUsername: 'creator',
25+
ownerAvatar: '/placeholder-avatar.jpg',
26+
},
27+
{
28+
id: '2',
29+
name: 'DeFi Protocol',
30+
description:
31+
'A decentralized finance protocol that enables automated yield farming and liquidity provision across multiple blockchain networks.',
32+
image: '/placeholder-image.jpg',
33+
link: '#',
34+
tags: ['defi', 'yield-farming', 'liquidity'],
35+
category: 'DeFi',
36+
type: 'defi',
37+
amount: 75000,
38+
status: 'funding',
39+
createdAt: '2024-01-15',
40+
updatedAt: '2024-01-15',
41+
owner: 'user456',
42+
ownerName: 'Another Creator',
43+
ownerUsername: 'creator2',
44+
ownerAvatar: '/placeholder-avatar.jpg',
45+
},
46+
{
47+
id: '3',
48+
name: 'NFT Marketplace',
49+
description:
50+
'A next-generation NFT marketplace with advanced features like batch minting, lazy minting, and cross-chain compatibility.',
51+
image: '/placeholder-image.jpg',
52+
link: '#',
53+
tags: ['nft', 'marketplace', 'cross-chain'],
54+
category: 'NFT',
55+
type: 'nft',
56+
amount: 100000,
57+
status: 'approved',
58+
createdAt: '2024-02-01',
59+
updatedAt: '2024-02-01',
60+
owner: 'user789',
61+
ownerName: 'Third Creator',
62+
ownerUsername: 'creator3',
63+
ownerAvatar: '/placeholder-avatar.jpg',
64+
},
65+
];
66+
67+
export default function PreviewPage() {
68+
const handleValidationClick = (projectId: string) => {
69+
alert(`Validation clicked for project: ${projectId}`);
70+
};
71+
72+
const handleVoteClick = (projectId: string) => {
73+
alert(`Vote clicked for project: ${projectId}`);
74+
};
75+
76+
return (
77+
<div className='min-h-screen bg-gray-900 py-12 px-4'>
78+
<div className='max-w-7xl mx-auto'>
79+
<div className='text-center mb-12'>
80+
<h1 className='text-4xl font-bold text-white mb-4'>
81+
Project Card Component Preview
82+
</h1>
83+
<p className='text-gray-400 text-lg'>
84+
Responsive design with GSAP animations
85+
</p>
86+
</div>
87+
88+
{/* Desktop Layout */}
89+
<div className='hidden lg:block'>
90+
<h2 className='text-2xl font-semibold text-gray-300 mb-8'>
91+
Desktop Layout (3 columns)
92+
</h2>
93+
<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8'>
94+
{mockProjects.map((project, index) => (
95+
<ProjectCard
96+
key={project.id}
97+
project={project}
98+
creatorName={project.ownerName}
99+
creatorAvatar={project.ownerAvatar}
100+
daysLeft={23 - index * 5}
101+
votes={{
102+
current: 46 + index * 15,
103+
total: 100,
104+
}}
105+
onValidationClick={() => handleValidationClick(project.id)}
106+
onVoteClick={() => handleVoteClick(project.id)}
107+
/>
108+
))}
109+
</div>
110+
</div>
111+
112+
{/* Tablet Layout */}
113+
<div className='hidden md:block lg:hidden'>
114+
<h2 className='text-2xl font-semibold text-gray-300 mb-8'>
115+
Tablet Layout (2 columns)
116+
</h2>
117+
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
118+
{mockProjects.slice(0, 2).map((project, index) => (
119+
<ProjectCard
120+
key={project.id}
121+
project={project}
122+
creatorName={project.ownerName}
123+
creatorAvatar={project.ownerAvatar}
124+
daysLeft={23 - index * 5}
125+
votes={{
126+
current: 46 + index * 15,
127+
total: 100,
128+
}}
129+
onValidationClick={() => handleValidationClick(project.id)}
130+
onVoteClick={() => handleVoteClick(project.id)}
131+
/>
132+
))}
133+
</div>
134+
</div>
135+
136+
{/* Mobile Layout */}
137+
<div className='block md:hidden'>
138+
<h2 className='text-2xl font-semibold text-gray-300 mb-8'>
139+
Mobile Layout (1 column)
140+
</h2>
141+
<div className='space-y-6'>
142+
{mockProjects.map((project, index) => (
143+
<ProjectCard
144+
key={project.id}
145+
project={project}
146+
creatorName={project.ownerName}
147+
creatorAvatar={project.ownerAvatar}
148+
daysLeft={23 - index * 5}
149+
votes={{
150+
current: 46 + index * 15,
151+
total: 100,
152+
}}
153+
onValidationClick={() => handleValidationClick(project.id)}
154+
onVoteClick={() => handleVoteClick(project.id)}
155+
/>
156+
))}
157+
</div>
158+
</div>
159+
160+
{/* Responsive Grid Test */}
161+
<div className='mt-16'>
162+
<h2 className='text-2xl font-semibold text-gray-300 mb-8'>
163+
Responsive Grid Test
164+
</h2>
165+
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 sm:gap-6'>
166+
{Array.from({ length: 8 }, (_, i) => {
167+
const project = mockProjects[i % mockProjects.length];
168+
return (
169+
<ProjectCard
170+
key={`test-${i}`}
171+
project={{
172+
...project,
173+
id: `test-${i}`,
174+
name: `Project ${i + 1}`,
175+
description: `This is a test project description for project ${i + 1}. It demonstrates the responsive behavior and animations of the component across different screen sizes.`,
176+
}}
177+
creatorName={`Creator ${i + 1}`}
178+
creatorAvatar='/placeholder-avatar.jpg'
179+
daysLeft={Math.floor(Math.random() * 30) + 1}
180+
votes={{
181+
current: Math.floor(Math.random() * 100),
182+
total: 100,
183+
}}
184+
onValidationClick={() => handleValidationClick(`test-${i}`)}
185+
onVoteClick={() => handleVoteClick(`test-${i}`)}
186+
/>
187+
);
188+
})}
189+
</div>
190+
</div>
191+
192+
{/* Instructions */}
193+
<div className='mt-16 bg-gray-800 rounded-lg p-6'>
194+
<h3 className='text-xl font-semibold text-white mb-4'>
195+
Preview Instructions
196+
</h3>
197+
<ul className='text-gray-300 space-y-2'>
198+
<li>
199+
<strong>Hover</strong> over cards to see GSAP hover animations
200+
</li>
201+
<li>
202+
<strong>Scroll</strong> to see entrance animations with scroll
203+
triggers
204+
</li>
205+
<li>
206+
<strong>Resize</strong> your browser to test responsive behavior
207+
</li>
208+
<li>
209+
<strong>Click</strong> buttons to see interaction feedback
210+
</li>
211+
<li>
212+
<strong>Mobile</strong>: Use browser dev tools to test mobile
213+
layout
214+
</li>
215+
</ul>
216+
</div>
217+
</div>
218+
</div>
219+
);
220+
}

0 commit comments

Comments
 (0)