Skip to content
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
2 changes: 2 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Personality from '../components/home/Personality';
import ProvostSection from '../components/home/ProvostSection';
import HeroSection from '../components/home/HeroSection'
import React from 'react'
import RecentEvent from '../components/home/RecentEvent';
Expand All @@ -20,6 +21,7 @@ const Home = () => {
isScroll={true}
/>
<Personality />
<ProvostSection />
<HistorySection />
<HomeHubsPreview />
<HomeClubsPreview />
Expand Down
57 changes: 52 additions & 5 deletions components/events/EventDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use client';

import Image from 'next/image';
import { MapPin, Calendar, ExternalLink, ArrowLeft } from 'lucide-react';
import { MapPin, Calendar, ExternalLink, ArrowLeft, Image as ImageIcon } from 'lucide-react';
import { EventItem } from '@/hooks/useEventCollection';
import Link from 'next/link';
import { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import remarkBreaks from 'remark-breaks';

interface EventDetailProps {
event: EventItem;
Expand All @@ -13,7 +16,7 @@ interface EventDetailProps {
const EventDetail: React.FC<EventDetailProps> = ({ event }) => {
const [mapLoading, setMapLoading] = useState(true);

const { title, description, eventDate, eventImage, venue, onlineLink } = event;
const { title, description, eventDate, eventImage, venue, onlineLink, eventImagesCollection } = event;

const dateObj = new Date(eventDate);
const formattedDate = dateObj.toLocaleDateString("en-US", {
Expand Down Expand Up @@ -74,12 +77,56 @@ const EventDetail: React.FC<EventDetailProps> = ({ event }) => {
<section className="bg-white rounded-3xl p-8 sm:p-10 shadow-sm border border-gray-100">
<h2 className="text-2xl font-bold text-gray-900 mb-6 font-header">About the Event</h2>
<div className="prose prose-lg text-gray-600 max-w-none">
{description.split('\n').map((paragraph, idx) => (
<p key={idx} className="mb-4 leading-relaxed whitespace-pre-wrap">{paragraph}</p>
))}
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkBreaks]}
components={{
p: ({ node, ...props }: any) => <p className="mb-6 leading-relaxed text-gray-700 text-lg" {...props} />,
ul: ({ node, ...props }: any) => <ul className="list-disc pl-6 mb-6 text-gray-700 text-lg" {...props} />,
ol: ({ node, ...props }: any) => <ol className="list-decimal pl-6 mb-6 text-gray-700 text-lg" {...props} />,
li: ({ node, ...props }: any) => <li className="mb-2 pl-2" {...props} />
}}
>
{description}
</ReactMarkdown>
</div>
</section>

{/* Media Gallery Section */}
{eventImagesCollection && eventImagesCollection.items.length > 0 && (
<section className="bg-white rounded-3xl p-8 sm:p-10 shadow-sm border border-gray-100">
<div className="flex items-center gap-3 mb-8">
<div className="bg-primary/10 p-2 rounded-xl">
<ImageIcon className="text-primary w-6 h-6" />
</div>
<h2 className="text-2xl font-bold text-gray-900 font-header">Media & Gallery</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{eventImagesCollection.items.map((asset, index) => (
<div
key={index}
className="group relative h-[300px] w-full rounded-2xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-300"
>
<Image
src={asset.url}
alt={asset.description || asset.title || `Event item ${index + 1}`}
fill
className="object-cover transition-transform duration-500 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors" />
{asset.title && (
<div className="absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/80 to-transparent translate-y-full group-hover:translate-y-0 transition-transform">
<p className="text-white font-medium text-sm">{asset.title}</p>
{asset.description && (
<p className="text-white/70 text-xs mt-1 line-clamp-1">{asset.description}</p>
)}
</div>
)}
</div>
))}
</div>
</section>
)}

{/* Map Section */}
<section className="bg-white rounded-3xl overflow-hidden shadow-sm border border-gray-100">
<div className="p-8 sm:p-10 border-b border-gray-100">
Expand Down
138 changes: 138 additions & 0 deletions components/home/ProvostSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
'use client';

import Image from 'next/image';
import { motion } from 'framer-motion';
import Container from '../custom/Container';
import { Award, BookOpen, GraduationCap, Briefcase } from 'lucide-react';

const ProvostSection = () => {
const highlights = [
{
icon: <GraduationCap className="w-5 h-5" />,
text: "30 Years Experience",
label: "Teaching & Research"
},
{
icon: <Award className="w-5 h-5" />,
text: "Provost",
label: "College of Engineering"
},
{
icon: <BookOpen className="w-5 h-5" />,
text: "100+ Publications",
label: "Peer-reviewed Journals"
},
{
icon: <Briefcase className="w-5 h-5" />,
text: "Patron",
label: "GESA-KNUST"
}
];

return (
<section className="py-24 bg-gradient-to-b from-white to-gray-50 overflow-hidden">
<Container size="xl">
<div className="flex flex-col lg:flex-row items-center gap-16 lg:gap-24">
<motion.div
initial={{ opacity: 0, x: -50 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8, ease: "easeOut" }}
className="relative w-full lg:w-1/2"
>
<div className="relative group">
<div className="absolute -inset-4 bg-primary/10 rounded-[2.5rem] -rotate-3 transition-transform group-hover:rotate-0 duration-500" />
<div className="absolute -inset-4 border-2 border-primary/20 rounded-[2.5rem] rotate-2 transition-transform group-hover:rotate-0 duration-500" />

<div className="relative h-[500px] sm:h-[600px] w-full rounded-2xl overflow-hidden shadow-2xl z-10">
<Image
src="/images/Provost.jpg"
alt="Professor Kwabena Biritwum Nyarko"
fill
className="object-cover transition-transform duration-700 group-hover:scale-105"
priority
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/40 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
</div>

<motion.div
initial={{ opacity: 0, scale: 0.8, rotate: 12 }}
whileInView={{ opacity: 1, scale: 1, rotate: 12 }}
viewport={{ once: true }}
transition={{ delay: 0.5, duration: 0.5 }}
className="absolute -bottom-6 -right-6 bg-white p-6 rounded-3xl shadow-2xl z-20 border border-gray-100 hidden md:block"
>
<p className="text-primary font-bold text-lg mb-1">GESA Patron</p>
<p className="text-gray-500 text-sm font-medium leading-tight">Celebrating Excellence &<br />Leadership at KNUST</p>
</motion.div>
</div>
</motion.div>

{/* Content */}
<div className="w-full lg:w-1/2 space-y-8">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
className="space-y-4"
>
<div className="inline-flex items-center gap-2 px-4 py-2 bg-primary/10 text-primary rounded-full text-sm font-bold tracking-wider uppercase">
<Award className="w-4 h-4" />
GESA PATRON
</div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-black text-gray-900 font-header leading-[1.1]">
Prof. Kwabena <span className="text-primary">Biritwum Nyarko</span>
</h2>
<p className="text-xl md:text-2xl text-gray-600 font-medium">
Provost, College of Engineering — KNUST
</p>
</motion.div>

<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.2 }}
className="prose prose-lg text-gray-600 max-w-none space-y-4"
>
<p className="leading-relaxed">
{`Professor Kwabena Biritwum Nyarko is a Professor at the Civil Engineering Department of Kwame Nkrumah University of Science and Technology, Kumasi, Ghana. He has 30 years of teaching and research experience in Water and Sanitation. His research focuses on water transport and distribution, sanitation technologies, and sustainable water and sanitation service delivery.`}
</p>
<p className="leading-relaxed hidden sm:block">
{`He is the Provost of the College of Engineering at KNUST and a valued member of the Regional Water and Sanitation Centre, Kumasi (RWESCK). He serves on the Board of the Engineering Council of Ghana and is a Council member of the Ghana Institution of Engineers.`}
</p>
<p className="leading-relaxed italic text-sm text-gray-500">
{`Prof Nyarko has over one hundred (100) publications in peer-reviewed journals, conference proceedings, and technical reports.`}
</p>
</motion.div>

<div className="grid grid-cols-2 gap-4 pt-4">
{highlights.map((item, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.4 + (index * 0.1) }}
className="p-4 bg-white border border-gray-100 rounded-2xl shadow-sm hover:shadow-md transition-shadow"
>
<div className="text-primary mb-2 bg-primary/5 w-fit p-2 rounded-lg">
{item.icon}
</div>
<p className="font-bold text-gray-900 group-hover:text-primary transition-colors">
{item.text}
</p>
<p className="text-xs text-gray-500 font-medium uppercase tracking-wider">
{item.label}
</p>
</motion.div>
))}
</div>
</div>
</div>
</Container>
</section>
);
};

export default ProvostSection;
21 changes: 21 additions & 0 deletions hooks/useEventCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ export interface EventItem {
venueInPlainEnglish: string;
onlineLink?: string;
eventImage: EventImage;
eventImagesCollection?: {
items: {
title: string;
description: string;
url: string;
}[];
};
}

interface Props {
Expand Down Expand Up @@ -49,6 +56,13 @@ const GET_EVENTS = gql`
url
description
}
eventImagesCollection {
items {
title
description
url
}
}
}
}
}
Expand All @@ -73,6 +87,13 @@ const GET_EVENT_BY_SLUG = gql`
url
description
}
eventImagesCollection {
items {
title
description
url
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/contentful-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ export const contentfulClient = new GraphQLClient(
...(CONTENTFUL_ACCESS_TOKEN ? { Authorization: `Bearer ${CONTENTFUL_ACCESS_TOKEN}` } : {}),
},
// @ts-ignore
next: { revalidate: 3600 },
next: { revalidate: 600 },
}
);
Binary file added public/images/Provost.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.