Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add boardmember collectiontype for nicer layout #247

Merged
merged 2 commits into from
Oct 13, 2024
Merged
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
42 changes: 42 additions & 0 deletions backend/src/api/boardmember/content-types/boardmember/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"kind": "collectionType",
"collectionName": "boardmembers",
"info": {
"singularName": "boardmember",
"pluralName": "boardmembers",
"displayName": "Bestuurslid",
"description": ""
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"name": {
"type": "string",
"required": true
},
"role": {
"type": "string",
"required": false
},
"email": {
"type": "email",
"required": false
},
"extra": {
"type": "richtext"
},
"photo": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": ["images"]
},
"order": {
"type": "integer",
"required": true,
"default": 10
}
}
}
9 changes: 9 additions & 0 deletions backend/src/api/boardmember/controllers/boardmember.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";

/**
* boardmember controller
*/

const { createCoreController } = require("@strapi/strapi").factories;

module.exports = createCoreController("api::boardmember.boardmember");
9 changes: 9 additions & 0 deletions backend/src/api/boardmember/routes/boardmember.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";

/**
* boardmember router
*/

const { createCoreRouter } = require("@strapi/strapi").factories;

module.exports = createCoreRouter("api::boardmember.boardmember");
9 changes: 9 additions & 0 deletions backend/src/api/boardmember/services/boardmember.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";

/**
* boardmember service
*/

const { createCoreService } = require("@strapi/strapi").factories;

module.exports = createCoreService("api::boardmember.boardmember");
54 changes: 54 additions & 0 deletions frontend/src/components/BoardmemberCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import Image from "next/image";
import imageLoader from "../utils/image-loader";
import { Boardmember } from "../models/Boardmember";
import Subheader from "./Subheader";
import { IconContext } from "react-icons";
import { FaEnvelope, FaPhone } from "react-icons/fa";
import Markdown from "./Markdown";

interface Props {
boardmember: Boardmember;
}

export default function BoardmemberCard(props: Props) {
const boardmember = props.boardmember;
return (
<div className="flex flex-col md:flex-row gap-8 mb-8 shadow-inner bg-gray-50 p-4 rounded">
<div className="float-right relative md:min-w-[10rem] h-[10rem] rounded shadow-lg overflow-hidden">
{boardmember.photo && (
<Image
src={boardmember.photo}
fill
sizes="10rem"
className="object-cover"
loader={imageLoader}
alt={`Foto van ${boardmember.name}`}
/>
)}
</div>
<div>
<Subheader>{boardmember.name}</Subheader>
<p>{boardmember.role}</p>
<div className="flex flex-col text-base my-4 gap-4 text-primary">
<IconContext.Provider
value={{
className:
"!text-primary origin-center group-hover:scale-125 transition-transform inline mr-2",
}}
>
<p>
<a
className="group hover:underline"
href={`mailto:${boardmember.email}`}
>
{boardmember.email && <FaEnvelope />}
{boardmember.email}
</a>
</p>
</IconContext.Provider>
</div>
<Markdown content={boardmember.extra} />
</div>
</div>
);
}
7 changes: 7 additions & 0 deletions frontend/src/models/Boardmember.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface Boardmember {
name: string;
role: string;
email: string;
extra: string;
photo: string;
}
21 changes: 16 additions & 5 deletions frontend/src/pages/over-ons.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { fetchAboutUs } from "../utils/backend";
import { fetchAboutUs, fetchBoardmembers } from "../utils/backend";
import AboutUsContent from "../models/AboutUsContent";
import Markdown from "../components/Markdown";
import Banner from "../components/Banner";
import Main from "../components/Main";
import { GetStaticPropsResult } from "next";
import { revalidate } from "../utils/revalidate";
import HeadPage from "../components/HeadPage";
import BoardmemberCard from "../components/BoardmemberCard";
import { Boardmember } from "../models/Boardmember";

interface Props {
content: AboutUsContent;
boardmembers: Boardmember[];
}

export default function OverOnsPage(props: Props) {
Expand All @@ -21,17 +24,25 @@ export default function OverOnsPage(props: Props) {
/>
<Banner title="Over ons" background={props.content.banner} compact />
<Main className="container">
<Markdown content={props.content.content} />
<div className="mb-8">
<Markdown content={props.content.content} />
</div>
{props.boardmembers.map((boardmember) => (
<BoardmemberCard key={boardmember.name} boardmember={boardmember} />
))}
</Main>
</div>
);
}

export async function getStaticProps(): Promise<GetStaticPropsResult<Props>> {
const [content, boardmembers] = await Promise.all([
fetchAboutUs(),
fetchBoardmembers(),
]);

return {
props: {
content: await fetchAboutUs(),
},
props: { content, boardmembers },
revalidate,
};
}
21 changes: 21 additions & 0 deletions frontend/src/utils/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import ProgramContent from "../models/ProgramContent";
import Fallback from "../models/Fallback";
import { PetitionDetail } from "../models/Petition";
import WorkgroupPageContent from "../models/WorkgroupPageContent";
import { Boardmember } from "../models/Boardmember";

export const backendBaseUrl =
process.env.BACKEND_URL ?? process.env.NEXT_PUBLIC_BACKEND_URL ?? "";
Expand Down Expand Up @@ -84,6 +85,26 @@ export async function fetchAboutUs(): Promise<AboutUsContent> {
return sanitise(response.data.data.attributes);
}

export async function fetchBoardmembers(): Promise<Boardmember[]> {
const response = await backend.get<StrapiListResponse<Boardmember>>("/boardmembers", {
params: {
sort: "order",
populate: {
photo: {
fields: ["url"],
},
},
},
});

function sanitise(boardmember: any): Boardmember {
boardmember.photo = boardmember.photo.data?.attributes?.url ?? null;
return boardmember;
}

return response.data.data.map((it) => sanitise(it.attributes));
}

export async function fetchProgram(): Promise<ProgramContent> {
const response = await backend.get<StrapiResponse<ProgramContent>>("/program", {
params: {
Expand Down
Loading