Skip to content

Commit 895b9d5

Browse files
authored
feat: donation form step 4 (#73)
* feat: rough styling for step 4, carousel * feat: donation form step 4 styles, components, socials * fix: make progress bar filled on final step * fix: reuse shadcn components, replace carousel placeholder
1 parent 1099d77 commit 895b9d5

10 files changed

Lines changed: 214 additions & 257 deletions

File tree

apps/frontend/src/api/apiClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import axios, { type AxiosInstance } from 'axios';
22

33
const defaultBaseUrl =
4-
import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3000';
4+
import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3001';
55

66
export type DonationCreateRequest = {
77
firstName: string;
31.6 KB
Loading
75.9 KB
Loading

apps/frontend/src/assets/x.png

12.9 KB
Loading

apps/frontend/src/components/ui/button.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const buttonVariants = cva(
1616
'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
1717
destructive:
1818
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
19+
success: 'bg-[#007B64] text-white hover:bg-[#006654] transition-colors',
20+
share:
21+
'bg-[#007B64] text-white hover:bg-[#006654] transition-colors w-[269px] h-[71px] rounded-[10px] font-semibold text-lg',
1922
link: 'text-primary underline-offset-4 hover:underline',
2023
unstyled: '',
2124
},
@@ -44,10 +47,13 @@ function Button({
4447
variant = 'default',
4548
size = 'default',
4649
asChild = false,
50+
withShareIcon = false,
51+
children,
4752
...props
4853
}: React.ComponentProps<'button'> &
4954
VariantProps<typeof buttonVariants> & {
5055
asChild?: boolean;
56+
withShareIcon?: boolean;
5157
}) {
5258
const Comp = asChild ? Slot : 'button';
5359
return (
@@ -57,7 +63,25 @@ function Button({
5763
data-size={size}
5864
className={cn(buttonVariants({ variant, size, className }))}
5965
{...props}
60-
/>
66+
>
67+
{children}
68+
{withShareIcon && (
69+
<svg
70+
width="20"
71+
height="20"
72+
viewBox="0 0 24 24"
73+
fill="none"
74+
stroke="currentColor"
75+
strokeWidth="2"
76+
strokeLinecap="round"
77+
strokeLinejoin="round"
78+
>
79+
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
80+
<polyline points="16 6 12 2 8 6" />
81+
<line x1="12" y1="2" x2="12" y2="15" />
82+
</svg>
83+
)}
84+
</Comp>
6185
);
6286
}
6387
export { Button, buttonVariants };

apps/frontend/src/containers/donations/donations.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@
328328
width: 31%;
329329
aspect-ratio: 14 / 1;
330330
border-radius: 10px;
331-
background: #650d77;
331+
background: #3D3E6E;
332332
}
333333

334334
.step2-container {
Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,130 @@
1-
import React from 'react';
1+
'use client';
2+
3+
import React, { useState } from 'react';
4+
import { Textarea } from '@components/ui/textarea';
5+
import { Button } from '@components/ui/button';
6+
import { TestimonialCarousel } from '@components/testimonials/TestimonialCarousel';
7+
import CarouselImage1 from '@components/testimonials/TestimonialImages/Carousel_image1.png';
8+
import CarouselImage2 from '@components/testimonials/TestimonialImages/Carousel_image2.png';
9+
import CarouselImage3 from '@components/testimonials/TestimonialImages/Carousel_image3.png';
210

311
interface Step4ReceiptProps {
4-
receiptId: string | null;
12+
receiptId?: string | null;
513
}
614

15+
const TESTIMONIAL_SLIDES = [
16+
{
17+
id: 1,
18+
image: CarouselImage1,
19+
alt: 'Testimonial image 1',
20+
},
21+
{
22+
id: 2,
23+
image: CarouselImage2,
24+
alt: 'Testimonial image 2',
25+
},
26+
{
27+
id: 3,
28+
image: CarouselImage3,
29+
alt: 'Testimonial image 3',
30+
},
31+
];
32+
733
export const Step4Receipt: React.FC<Step4ReceiptProps> = () => {
34+
const [feedback, setFeedback] = useState('');
35+
36+
const handleSpreadTheWord = () => {
37+
if (navigator.share) {
38+
navigator
39+
.share({
40+
title: 'I just donated to FCC!',
41+
text: 'Join me in supporting FCC and making a difference in our community.',
42+
url: window.location.origin,
43+
})
44+
.catch((error) => {
45+
if (error.name !== 'AbortError') {
46+
console.error('Error sharing:', error);
47+
}
48+
});
49+
}
50+
};
51+
852
return (
9-
<section>
10-
<h3>Step 4: Receipt</h3>
11-
<p>Thank you for your donation!</p>
12-
</section>
53+
<div className="mx-auto w-full max-w-[600px] px-4 py-8">
54+
<div className="text-center">
55+
<h1 className="text-5xl font-black tracking-tight text-[#2d3161] md:text-6xl scale-y-125 scale-x-90 [font-family:'Helvetica_Neue',Helvetica,Arial,sans-serif] [font-weight:900]">
56+
THANK YOU
57+
</h1>
58+
<p className="mt-2 text-black text-[32px] leading-[25px] tracking-[0] text-center [font-family:'Helvetica_Neue',Helvetica,Arial,sans-serif] [font-weight:200]">
59+
For making a difference.
60+
</p>
61+
</div>
62+
<div className="mt-6 flex items-center justify-center gap-4">
63+
<div className="h-px w-20 bg-gray-300" />
64+
<p className="text-[14px] text-gray-400 whitespace-nowrap">
65+
A receipt has been sent to your email.
66+
</p>
67+
<div className="h-px w-20 bg-gray-300" />
68+
</div>
69+
<div className="mt-10">
70+
<label className="mb-3 block text-left">
71+
<span className="text-black text-[16px] leading-[100%] tracking-[0] font-normal [font-family:Helvetica,Arial,sans-serif]">
72+
What made you donate to FCC today?
73+
</span>{' '}
74+
<span className="text-gray-400 text-[16px] leading-[100%] tracking-[0] font-normal [font-family:Helvetica,Arial,sans-serif]">
75+
(optional)
76+
</span>
77+
</label>
78+
<Textarea
79+
value={feedback}
80+
onChange={(e) => setFeedback(e.target.value)}
81+
placeholder="Share with us here"
82+
className="min-h-[120px]"
83+
rows={4}
84+
/>
85+
</div>
86+
<div className="mt-8 mb-8">
87+
<TestimonialCarousel slides={TESTIMONIAL_SLIDES} />
88+
</div>
89+
<div className="flex justify-center gap-10 mb-8">
90+
<a
91+
href="https://www.facebook.com/sharer/sharer.php"
92+
target="_blank"
93+
rel="noopener noreferrer"
94+
className="transition-opacity hover:opacity-80"
95+
>
96+
<img
97+
src="/src/assets/facebook.png"
98+
alt="Share on Facebook"
99+
className="w-12 h-12"
100+
/>
101+
</a>
102+
<a
103+
href="https://twitter.com/intent/tweet"
104+
target="_blank"
105+
rel="noopener noreferrer"
106+
className="transition-opacity hover:opacity-80"
107+
>
108+
<img src="/src/assets/x.png" alt="Share on X" className="w-12 h-12" />
109+
</a>
110+
<a
111+
href="https://www.linkedin.com/sharing/share-offsite/"
112+
target="_blank"
113+
rel="noopener noreferrer"
114+
className="transition-opacity hover:opacity-80"
115+
>
116+
<img
117+
src="/src/assets/linkedin.png"
118+
alt="Share on LinkedIn"
119+
className="w-12 h-12"
120+
/>
121+
</a>
122+
</div>
123+
<div className="mt-8 flex justify-center">
124+
<Button variant="share" withShareIcon onClick={handleSpreadTheWord}>
125+
Spread the word!
126+
</Button>
127+
</div>
128+
</div>
13129
);
14130
};

apps/frontend/vite.config.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ export default defineConfig({
1111
server: {
1212
port: 4200,
1313
host: 'localhost',
14+
proxy: {
15+
'/api': {
16+
target: 'http://localhost:3001',
17+
changeOrigin: true,
18+
secure: false,
19+
},
20+
},
1421
fs: {
1522
allow: [
1623
// Allow serving from project root and above

components.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": false,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "",
8+
"css": "src/styles/globals.css",
9+
"baseColor": "neutral",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils",
16+
"ui": "@/components/ui",
17+
"lib": "@/lib",
18+
"hooks": "@/hooks"
19+
},
20+
"iconLibrary": "lucide"
21+
}

0 commit comments

Comments
 (0)