Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ model Corps {
language String @default("sv")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
contactURL String?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not 100% convinced adding contactURL to Corps is a good idea. I would prefer adding a new model Position which defines a name, contactUrl and maybe links to some of the permission roles.

E.g. for the Kassör:

{
    name: "Kassör",
    nameEn: "Treasurer",
    email: "kassor@bleckhornen.org",
    contactUrl: null, // Google form for Trivselombud
    permissionRoleId: <id>,
}

Another solution could be to add email and contactUrl to Role, and create new roles for each board member and commitee chairman. Could be worth adding nameEn/nameEnglish as well to store the English translation.


roles Role[]
permissions Permission[]
Expand Down
12 changes: 12 additions & 0 deletions src/app/account/preferences.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const initialValues = {
lactoseFree: false,
otherFoodPrefs: '',
email: '',
contactURL: '',
mainInstrument: '',
};
type FormValues = typeof initialValues;
Expand Down Expand Up @@ -59,6 +60,7 @@ const AccountPreferences = () => {
lactoseFree: corps.foodPrefs?.lactoseFree ?? false,
otherFoodPrefs: corps.foodPrefs?.other ?? '',
email: corps.user.email || undefined,
contactURL: corps.contactURL ?? '',
mainInstrument,
});
}, [corps]);
Expand Down Expand Up @@ -86,6 +88,8 @@ const AccountPreferences = () => {
label: i.instrument.name,
}));

const isTrivselOmbud = corps?.roles.some(role => role.name === "Trivselombud");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to keep the code in English. Although in this case it might be acceptable as we are looking for a role called "Trivselombud".


return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<FormLoadingOverlay visible={submitting || corpsLoading}>
Expand Down Expand Up @@ -155,6 +159,14 @@ const AccountPreferences = () => {
label={lang('Pronomen', 'Pronouns')}
{...form.getInputProps('pronouns')}
/>
{
(isTrivselOmbud) &&
(<TextInput
label={lang('Kontakt URL', 'Contact URL')}
{...form.getInputProps('contactURL')}
/>)
}

</div>
<div className='flex flex-col gap-2 pl-2'>
<h3>{lang('Matpreferenser', 'Food preferences')}</h3>
Expand Down
324 changes: 324 additions & 0 deletions src/app/info/page.tsx

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/app/links/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ const Links = () => {
{lang('Notdriven', 'The Note Drive')}
</a>
</li>
<li>
<a
className='cursor-pointer text-red-600 underline'
href='https://samply.app/p/Ub5REp3lbAi3CCnJdgdm'
>
{lang(
'Samply, en hemsida där man kan streama våra låtar.',
'Samply, a website where you can stream our songs.',
)}
</a>
</li>
<li>
<a
className='cursor-pointer text-red-600 underline'
Expand Down
3 changes: 3 additions & 0 deletions src/components/corps-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const initialValues = {
number: '',
bNumber: '',
email: '',
contactURL: '',
mainInstrument: '',
otherInstruments: [] as string[],
roles: [] as Permission[],
Expand Down Expand Up @@ -78,6 +79,7 @@ const CorpsForm = ({ corpsId }: AdminCorpsProps) => {
number: corps.number?.toString() || '',
bNumber: corps.bNumber?.toString() || '',
email: corps.user.email ?? '',
contactURL: corps.contactURL ?? '',
mainInstrument,
otherInstruments,
roles: corps.roles.map((r) => r.name as Permission),
Expand Down Expand Up @@ -133,6 +135,7 @@ const CorpsForm = ({ corpsId }: AdminCorpsProps) => {
</div>
<TextInput label='Smeknamn' {...form.getInputProps('nickName')} />
<TextInput label='Pronomen' {...form.getInputProps('pronouns')} />
<TextInput label='Kontakt URL' {...form.getInputProps('contactURL')} />
<div className='flex gap-4'>
<TextInput label='Nummer' {...form.getInputProps('number')} />
<TextInput label='Balettnr.' {...form.getInputProps('bNumber')} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/corps/infobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const CorpsInfobox = ({ id, open }: CorpsInfoboxProps) => {

const joinedAt =
(firstGigDate?.getTime() ?? Number.MAX_VALUE) <
(firstRehearsalDate?.getTime() ?? Number.MAX_VALUE)
(firstRehearsalDate?.getTime() ?? Number.MAX_VALUE)
? firstGigDate
: firstRehearsalDate;

Expand Down
161 changes: 161 additions & 0 deletions src/components/corps/position-infobox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { IconMail } from '@tabler/icons-react';
import ActionIcon from 'components/input/action-icon';
import { filterNone } from 'utils/array';
import { numberAndFullName } from 'utils/corps';
import { lang } from 'utils/language';

interface Instrument {
instrument: { name: string };
isMainInstrument: boolean;
}

interface Role {
name: string;
}

interface Corps {
id: string;
firstName: string;
lastName: string;
nickName: string | null;
pronouns: string | null;
number: number | null;
bNumber: number | null;
contactURL: string | null;
points: number;
firstGigDate: Date | undefined;
firstRehearsalDate: Date | undefined;
instruments: Instrument[];
roles: Role[];
}

interface CorpsInfoboxProps {
corps: Corps;
}

const genOtherInstrumentsString = (instruments: string[]) => {
const instrumentsLower = instruments.map((i) => i.toLowerCase());
if (instrumentsLower.length === 0) return '';
if (instrumentsLower.length === 1) return instrumentsLower[0] ?? '';
return `${instrumentsLower
.slice(0, instrumentsLower.length - 1)
.join(', ')} och ${instrumentsLower[instrumentsLower.length - 1] ?? ''}`;
};

const roleToEmail: Record<string, string> = {
Ordförande: "ordforande@bleckhornen.org",
ViceOrdförande: "vice@bleckhornen.org",
Sekreterare: "sekreterare@bleckhornen.org",
Kassör: "kassor@bleckhornen.org",
};

const roleListToEmail = (roles: Role[]) => {
const matchingRole = roles.find(r => roleToEmail[r.name]);

return matchingRole ? ('mailto:' + roleToEmail[matchingRole.name]) : null;
}

// A list of "instruments" which should have the prefix "är"
const beingPrefixes = ['dirigent', 'balett', 'slagverksfröken'];


const PositionInfobox = ({ corps }: CorpsInfoboxProps) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should redesign the info card a bit. If we simply use CorpsDisplay on the position infopage the user can see this info by clicking the name.

It should be enough to just display the name of the committee, the description, and who is responsible.

const corpsNameTemp = numberAndFullName(corps);
const corpsName =
corpsNameTemp.length > 25
? corpsNameTemp.slice(0, 25) + corpsNameTemp.slice(25).replace(' ', '\n')
: corpsNameTemp;

const {
nickName,
pronouns,
contactURL,
points,
firstGigDate,
firstRehearsalDate,
instruments
} = corps;

const mainInstrument =
instruments.find((i) => i.isMainInstrument)?.instrument.name ?? '';
const otherInstruments = instruments
.filter((i) => !i.isMainInstrument)
.map((i) => i.instrument.name);

const isPlayingMainInstrument = !beingPrefixes.includes(
mainInstrument.toLowerCase(),
);
const isPlayingOtherInstrument = !otherInstruments.some((i) =>
beingPrefixes.includes(i.toLowerCase()),
);


const joinedAt =
(firstGigDate?.getTime() ?? Number.MAX_VALUE) <
(firstRehearsalDate?.getTime() ?? Number.MAX_VALUE)
? firstGigDate
: firstRehearsalDate;

const joinedMsg = `Gick med i corpset den ${joinedAt?.getDate()} ${joinedAt?.toLocaleDateString(
'sv',
{ month: 'long' },
)} ${joinedAt?.getFullYear()}.`;

const temp1 = isPlayingMainInstrument ? 'Spelar ' : 'Är ';

// If the main instrument is the same as the other instruments, we don't need to specify it twice
const temp2 =
isPlayingMainInstrument !== isPlayingOtherInstrument
? isPlayingOtherInstrument
? 'spelar '
: 'är '
: '';

const instrumentsMsg =
temp1 +
(otherInstruments.length > 0 ? 'främst ' : '') +
mainInstrument.toLowerCase() +
(otherInstruments.length > 0
? ', men ' + temp2 + 'även ' + genOtherInstrumentsString(otherInstruments)
: '') +
'.';

const roleEmail = roleListToEmail(corps.roles)
const contact = roleEmail ? roleEmail : contactURL

return (
<div>
<div className='text-lg font-bold'>
<div className='flex flex-nowrap items-start gap-2 whitespace-pre'>
{corpsName}

{(contact) && (
<ActionIcon
href={contact}
variant='subtle'
>
<IconMail />
</ActionIcon>
)}
</div>
{(nickName || pronouns) && (
<div className='mb-1 bg-transparent text-xs font-light text-neutral-500'>
{filterNone([corps.nickName, corps.pronouns]).join(' • ')}
</div>
)}
</div>
<div className='italic'>
{lang('Spelpoäng: ', 'Gig points: ')}
{points}
</div>
<div className='h-1.5' />
<div className='text-sm font-light'>
{joinedAt && joinedMsg} {instrumentsMsg}{' '}

</div>

</div>
);
};

export default PositionInfobox;
6 changes: 6 additions & 0 deletions src/components/navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
IconClipboardList,
IconHome,
IconInfoSquare,
IconInfoCircle,
IconKey,
IconLink,
IconMicrophone2,
Expand Down Expand Up @@ -61,6 +62,11 @@ const userTab: NavbarLinkGroup = {
},
{ label: lang('Sånger', 'Songs'), href: '/songs', icon: <IconMusic /> },
{ label: lang('Länkar', 'Links'), href: '/links', icon: <IconLink /> },
{
label: lang('Om Bleckhornen', 'About Bleckhornen'),
href: '/info',
icon: <IconInfoCircle />,
},
],
};
const adminTab: NavbarLinkGroup = {
Expand Down
6 changes: 6 additions & 0 deletions src/server/trpc/router/corps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export const corpsRouter = router({
nickName: z.string().transform(emptyToNull),
pronouns: z.string().transform(emptyToNull),
email: z.string(),
contactURL: z.string(),
vegetarian: z.boolean(),
vegan: z.boolean(),
glutenFree: z.boolean(),
Expand All @@ -154,6 +155,7 @@ export const corpsRouter = router({
nickName,
pronouns,
email,
contactURL,
vegetarian,
vegan,
glutenFree,
Expand Down Expand Up @@ -217,6 +219,7 @@ export const corpsRouter = router({
data: {
nickName,
pronouns,
contactURL,
user: {
update: {
email: email.trim(),
Expand All @@ -243,6 +246,7 @@ export const corpsRouter = router({
number: z.number().nullable(),
bNumber: z.number().nullable(),
email: z.string(),
contactURL: z.string(),
mainInstrument: z.string(),
otherInstruments: z.array(z.string()),
roles: z.array(z.string()),
Expand All @@ -261,6 +265,8 @@ export const corpsRouter = router({
input.nickName.trim().length > 0 ? input.nickName.trim() : null,
pronouns:
input.pronouns.trim().length > 0 ? input.pronouns.trim() : null,
contactURL:
input.contactURL.trim().length > 0 ? input.contactURL.trim() : null,
number: input.number,
bNumber: input.bNumber,
instruments: {
Expand Down