Skip to content

Commit ac27437

Browse files
feat: add supporter selector
Co-authored-by: Adrian Polak <[email protected]>
1 parent 99a7336 commit ac27437

File tree

9 files changed

+126
-76
lines changed

9 files changed

+126
-76
lines changed

src/components/event-form/event-form-controls.tsx

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
import { Checkbox, DatePicker, Input, Select, SelectItem } from '@heroui/react';
1+
import {
2+
Checkbox,
3+
DatePicker,
4+
Input,
5+
Radio,
6+
RadioGroup,
7+
Select,
8+
SelectItem,
9+
} from '@heroui/react';
210
import { fromDate, getLocalTimeZone } from '@internationalized/date';
311
import { Controller } from 'react-hook-form';
412

13+
import { Supporter } from '@/components/event-form/event-form-types';
514
import { cities } from '@/data/cities';
615

716
import type { UseFormReturn } from 'react-hook-form';
@@ -15,7 +24,7 @@ interface EventFormControlsProps {
1524
export const EventFormControls = ({
1625
form: { control, setValue, watch },
1726
}: EventFormControlsProps) => {
18-
const withPartners = watch('withPartners');
27+
const withSupporters = watch('withSupporters');
1928

2029
return (
2130
<>
@@ -84,30 +93,50 @@ export const EventFormControls = ({
8493
/>
8594
<Controller
8695
control={control}
87-
name="withPartners"
96+
name="withSupporters"
8897
render={({ field: { value, onChange, ...field } }) => (
8998
<Checkbox isSelected={value} onValueChange={onChange} {...field}>
90-
Partner
99+
Supporter
91100
</Checkbox>
92101
)}
93102
/>
94-
{withPartners && (
95-
<Controller
96-
control={control}
97-
name="partners"
98-
render={({ field: { onChange } }) => (
99-
<Input
100-
type="file"
101-
accept="image/*"
102-
multiple
103-
label="Partners' logos"
104-
isRequired
105-
onChange={({ target: { files } }) =>
106-
files && onChange([...files])
107-
}
108-
/>
109-
)}
110-
/>
103+
{withSupporters && (
104+
<>
105+
<Controller
106+
control={control}
107+
name="supporterImages"
108+
render={({ field: { onChange } }) => (
109+
<Input
110+
type="file"
111+
accept="image/*"
112+
multiple
113+
label="Supporters' logos"
114+
isRequired
115+
onChange={({ target: { files } }) =>
116+
files && onChange([...files])
117+
}
118+
/>
119+
)}
120+
/>
121+
<Controller
122+
control={control}
123+
name="supporter"
124+
render={({ field: { value, onChange, ...field } }) => (
125+
<RadioGroup
126+
isRequired
127+
label="Select supporter type"
128+
orientation="horizontal"
129+
value={value === null ? '' : value}
130+
onValueChange={value => onChange(value === '' ? null : value)}
131+
{...field}
132+
>
133+
<Radio value={Supporter.EventPartner}>Event partner</Radio>
134+
<Radio value={Supporter.Sponsor}>Sponsor</Radio>
135+
<Radio value="">Logo only</Radio>
136+
</RadioGroup>
137+
)}
138+
/>
139+
</>
111140
)}
112141
</>
113142
);

src/components/event-form/event-form-schema.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
import { z } from 'zod/v4';
22

3+
import { Supporter } from '@/components/event-form/event-form-types';
4+
35
const eventFormBaseSchema = z.object({
46
city: z.string().min(1),
57
title: z.string().min(1),
68
location: z.string().min(1),
79
date: z.date(),
810
});
911

10-
const eventFormPartnersSchema = z.object({
11-
withPartners: z.literal(true),
12-
partners: z.array(z.file()).min(1),
12+
const eventFormSupportersSchema = z.object({
13+
withSupporters: z.literal(true),
14+
supporter: z.enum(Supporter).nullable(),
15+
supporterImages: z.array(z.file()).min(1),
1316
});
1417

15-
const eventFormNoPartnersSchema = z.object({
16-
withPartners: z.literal(false),
18+
const eventFormNoSupportersSchema = z.object({
19+
withSupporters: z.literal(false),
1720
});
1821

1922
export const eventFormSchema = z.intersection(
2023
eventFormBaseSchema,
21-
z.discriminatedUnion('withPartners', [
22-
eventFormPartnersSchema,
23-
eventFormNoPartnersSchema,
24+
z.discriminatedUnion('withSupporters', [
25+
eventFormSupportersSchema,
26+
eventFormNoSupportersSchema,
2427
]),
2528
);
2629

src/components/event-form/event-form-thumbnail/event-form-thumbnail-sponsors.tsx

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Supporter } from '@/components/event-form/event-form-types';
2+
3+
interface EventFormThumbnailSupportersProps {
4+
readonly supporter: Supporter | null;
5+
readonly supporterImages: File[];
6+
}
7+
8+
export const EventFormThumbnailSupporters = ({
9+
supporter,
10+
supporterImages,
11+
}: EventFormThumbnailSupportersProps) => (
12+
<div className="relative flex h-full flex-col items-center justify-center bg-white">
13+
{supporter !== null && (
14+
<h2 className="text-2xl font-extrabold uppercase">
15+
{supporter === Supporter.EventPartner && 'Event Partner'}
16+
{supporter === Supporter.Sponsor && 'Sponsor'}
17+
{supporterImages.length > 1 && 's'}
18+
</h2>
19+
)}
20+
{supporterImages.map(supporter => (
21+
<img
22+
key={supporter.name}
23+
alt={supporter.name}
24+
src={URL.createObjectURL(supporter)}
25+
className="px-10"
26+
/>
27+
))}
28+
</div>
29+
);

src/components/event-form/event-form-thumbnail/event-form-thumbnail.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { EventFormThumbnailDetails } from '@/components/event-form/event-form-th
22
import { EventFormThumbnailLeftSectionDecorations } from '@/components/event-form/event-form-thumbnail/event-form-thumbnail-left-section-decorations.tsx';
33
import { EventFormThumbnailMeetjsLogo } from '@/components/event-form/event-form-thumbnail/event-form-thumbnail-meetjs-logo.tsx';
44
import { EventFormThumbnailRightSectionDecorations } from '@/components/event-form/event-form-thumbnail/event-form-thumbnail-right-section-decorations.tsx';
5-
import { EventFormThumbnailSponsors } from '@/components/event-form/event-form-thumbnail/event-form-thumbnail-sponsors.tsx';
5+
import { EventFormThumbnailSupporters } from '@/components/event-form/event-form-thumbnail/event-form-thumbnail-supporters.tsx';
66
import { EventFormThumbnailTitle } from '@/components/event-form/event-form-thumbnail/event-form-thumbnail-title.tsx';
77
import { formatDate, formatTime } from '@/lib/date-formatter';
88

@@ -48,9 +48,14 @@ export const EventFormThumbnail = ({ form, ref }: EventFormThumbnailProps) => {
4848
</div>
4949
<div className="relative col-span-1">
5050
<EventFormThumbnailRightSectionDecorations />
51-
{values.withPartners && values.partners?.length > 0 && (
52-
<EventFormThumbnailSponsors partners={values.partners} />
53-
)}
51+
{values.withSupporters &&
52+
values.supporter !== undefined &&
53+
values.supporterImages?.length > 0 && (
54+
<EventFormThumbnailSupporters
55+
supporter={values.supporter}
56+
supporterImages={values.supporterImages}
57+
/>
58+
)}
5459
</div>
5560
</article>
5661
</div>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum Supporter {
2+
EventPartner = 'EVENT_PARTNER',
3+
Sponsor = 'SPONSOR',
4+
}

src/components/event-form/use-event-form.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import kebabCase from 'lodash/kebabCase';
44
import { useRef } from 'react';
55
import { useForm } from 'react-hook-form';
66

7+
import { Supporter } from '@/components/event-form/event-form-types.ts';
78
import { downloadResource } from '@/lib/download-resource';
89

910
import { eventFormSchema } from './event-form-schema';
1011

1112
export const useEventForm = () => {
1213
const thumbnailRef = useRef<HTMLDivElement>(null);
1314
const form = useForm({
14-
defaultValues: { withPartners: false },
15+
defaultValues: { withSupporters: true, supporter: Supporter.Sponsor },
1516
resolver: zodResolver(eventFormSchema),
1617
});
1718

tsconfig.app.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"strict": true,
2424
"noUnusedLocals": true,
2525
"noUnusedParameters": true,
26-
"erasableSyntaxOnly": true,
2726
"noFallthroughCasesInSwitch": true,
2827
"noUncheckedSideEffectImports": true
2928
},

tsconfig.node.json

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
{
2-
"compilerOptions": {
3-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4-
"target": "ES2023",
5-
"lib": ["ES2023"],
6-
"module": "ESNext",
7-
"types": [],
8-
"skipLibCheck": true,
2+
"compilerOptions": {
3+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4+
"target": "ES2023",
5+
"lib": ["ES2023"],
6+
"module": "ESNext",
7+
"types": [],
8+
"skipLibCheck": true,
99

10-
/* Bundler mode */
11-
"moduleResolution": "bundler",
12-
"allowImportingTsExtensions": true,
13-
"verbatimModuleSyntax": true,
14-
"moduleDetection": "force",
15-
"noEmit": true,
10+
/* Bundler mode */
11+
"moduleResolution": "bundler",
12+
"allowImportingTsExtensions": true,
13+
"verbatimModuleSyntax": true,
14+
"moduleDetection": "force",
15+
"noEmit": true,
1616

17-
/* Linting */
18-
"strict": true,
19-
"noUnusedLocals": true,
20-
"noUnusedParameters": true,
21-
"erasableSyntaxOnly": true,
22-
"noFallthroughCasesInSwitch": true,
23-
"noUncheckedSideEffectImports": true
24-
},
25-
"include": ["vite.config.ts"]
17+
/* Linting */
18+
"strict": true,
19+
"noUnusedLocals": true,
20+
"noUnusedParameters": true,
21+
"noFallthroughCasesInSwitch": true,
22+
"noUncheckedSideEffectImports": true
23+
},
24+
"include": ["vite.config.ts"]
2625
}

0 commit comments

Comments
 (0)