diff --git a/src/app/(pages)/events/_components/EventsLoading.tsx b/src/app/(pages)/events/_components/EventsLoading.tsx new file mode 100644 index 00000000..ad437242 --- /dev/null +++ b/src/app/(pages)/events/_components/EventsLoading.tsx @@ -0,0 +1,23 @@ +import { Skeleton } from '@/components/ui/skeleton'; + +export default function EventCardLoading() { + return new Array(2).fill('').map(id => ( +
+
+
+ +
+
+
+ + + + + +
+
+ )); +} diff --git a/src/app/(pages)/events/page.tsx b/src/app/(pages)/events/page.tsx index 2ffc1e4b..27aca9da 100644 --- a/src/app/(pages)/events/page.tsx +++ b/src/app/(pages)/events/page.tsx @@ -1,32 +1,39 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import EventCard from './_components/EventCard'; import { getEvents } from '@/lib/notion/events'; import BlockContainer from '@/components/BlockContainer'; +import EventCardLoading from './_components/EventsLoading'; export const revalidate = Number(process.env.REVALIDATION_INTERVAL) || 3600; const EventsPage: React.FC = async () => { - const res = await getEvents(); return (
- {res.map(event => ( - - ))} + }> + +
); }; +async function Events() { + const res = await getEvents(); + return res.map(event => ( + + )); +} + export default EventsPage; diff --git a/src/app/(pages)/home/_components/EventsBlock.tsx b/src/app/(pages)/home/_components/EventsBlock.tsx index 5a3c6ec8..81435ade 100644 --- a/src/app/(pages)/home/_components/EventsBlock.tsx +++ b/src/app/(pages)/home/_components/EventsBlock.tsx @@ -3,13 +3,12 @@ import EventCard from './EventCard'; import { getFeaturedEvents } from '@/lib/notion/events'; import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; import { getFeaturedAnnouncements } from '@/lib/notion/announcements'; +import { Suspense } from 'react'; +import { HomeEventLoading } from './HomePageLoading'; export const revalidate = Number(process.env.REVALIDATION_INTERVAL) || 3600; -export default async function HomeEvents() { - const res = await getFeaturedEvents(); - const news = await getFeaturedAnnouncements(); - +export default function HomeEvents() { return (
@@ -20,18 +19,9 @@ export default async function HomeEvents() { }} className="w-full" > - - {news.map(announcement => ( - - - - ))} - {res.map(event => ( - - - - ))} - + }> + + @@ -40,3 +30,23 @@ export default async function HomeEvents() { ); } + +async function Events() { + const res = await getFeaturedEvents(); + const news = await getFeaturedAnnouncements(); + + return ( + + {news.map(announcement => ( + + + + ))} + {res.map(event => ( + + + + ))} + + ); +} diff --git a/src/app/(pages)/home/_components/HomePageLoading.tsx b/src/app/(pages)/home/_components/HomePageLoading.tsx new file mode 100644 index 00000000..841db2dc --- /dev/null +++ b/src/app/(pages)/home/_components/HomePageLoading.tsx @@ -0,0 +1,36 @@ +import { CarouselContent, CarouselItem } from '@/components/ui/carousel'; +import { Skeleton } from '@/components/ui/skeleton'; + +export function HomeProjectLoading() { + return ( + + {new Array(3).fill('').map(id => ( + +
+ +
+
+ ))} +
+ ); +} + +export function HomeProjectLoadingMobile() { + return new Array(3).fill('').map(id => ( +
+ +
+ )); +} + +export function HomeEventLoading() { + return ( + + {new Array(3).fill('').map(id => ( + + + + ))} + + ); +} diff --git a/src/app/(pages)/home/_components/ProjectsBlock.tsx b/src/app/(pages)/home/_components/ProjectsBlock.tsx index 89e66275..9dcd57f4 100644 --- a/src/app/(pages)/home/_components/ProjectsBlock.tsx +++ b/src/app/(pages)/home/_components/ProjectsBlock.tsx @@ -4,11 +4,12 @@ import Link from 'next/link'; import { MdDoubleArrow } from 'react-icons/md'; import { getFeaturedProjects } from '@/lib/notion/projects'; import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; +import { Suspense } from 'react'; +import { HomeProjectLoading, HomeProjectLoadingMobile } from './HomePageLoading'; export const revalidate = Number(process.env.REVALIDATION_INTERVAL) || 3600; export default async function ProjectsBlock() { - const featuredProjects = await getFeaturedProjects(); return (
@@ -19,20 +20,16 @@ export default async function ProjectsBlock() { }} className="hidden md:block" > - - {featuredProjects.map(project => ( - - - - ))} - + }> + +
- {featuredProjects.map(project => ( - - ))} + }> + +
@@ -49,3 +46,22 @@ export default async function ProjectsBlock() { ); } + +async function ProjectCards() { + const featuredProjects = await getFeaturedProjects(); + return ( + + {featuredProjects.map(project => ( + + + + ))} + + ); +} + +async function ProjectCardsMobile() { + const featuredProjects = await getFeaturedProjects(); + + return featuredProjects.map(project => ); +} diff --git a/src/app/(pages)/projects/_components/CurrentProjects.tsx b/src/app/(pages)/projects/_components/CurrentProjects.tsx index 23f192d9..c2daa3e3 100644 --- a/src/app/(pages)/projects/_components/CurrentProjects.tsx +++ b/src/app/(pages)/projects/_components/CurrentProjects.tsx @@ -1,16 +1,10 @@ import { v4 as uuidv4 } from 'uuid'; import ProjectCard from './ProjectCard'; -import { ProjectDataType } from '@/lib/notion/projects'; -import BlockContainer from '@/components/BlockContainer'; +import { getProjects, isCurrentProject } from '@/lib/notion/projects'; +// import BlockContainer from '@/components/BlockContainer'; -export default async function CurrentProjects({ projects }: { projects: ProjectDataType[] }) { - return ( - -
- {projects.map(project => ( - - ))} -
-
- ); +export default async function CurrentProjects() { + const res = await getProjects(); + const projects = res.filter(project => isCurrentProject(project)); + return projects.map(project => ); } diff --git a/src/app/(pages)/projects/_components/PastProjectCard.tsx b/src/app/(pages)/projects/_components/PastProjectCard.tsx index e68cbbae..9261b1dc 100644 --- a/src/app/(pages)/projects/_components/PastProjectCard.tsx +++ b/src/app/(pages)/projects/_components/PastProjectCard.tsx @@ -22,11 +22,13 @@ export default function PastProjectCard({ data }: { data: ProjectDataType }) { />
)} -
- {data.companyName} - -

{data.description}

-

{data.productName}

+
+
+ {data.companyName} +

{data.productName}

+
+ +

{data.description}

diff --git a/src/app/(pages)/projects/_components/PastProjects.tsx b/src/app/(pages)/projects/_components/PastProjects.tsx index 81657c67..264eaedb 100644 --- a/src/app/(pages)/projects/_components/PastProjects.tsx +++ b/src/app/(pages)/projects/_components/PastProjects.tsx @@ -1,16 +1,10 @@ import { v4 as uuidv4 } from 'uuid'; import PastProjectCard from './PastProjectCard'; -import { ProjectDataType } from '@/lib/notion/projects'; -import BlockContainer from '@/components/BlockContainer'; +import { getProjects, isCurrentProject } from '@/lib/notion/projects'; +// import BlockContainer from '@/components/BlockContainer'; -export default async function PastProjects({ projects }: { projects: ProjectDataType[] }) { - return ( - -
- {projects.map(project => ( - - ))} -
-
- ); +export default async function PastProjects() { + const res = await getProjects(); + const projects = res.filter(project => !isCurrentProject(project)); + return projects.map(project => ); } diff --git a/src/app/(pages)/projects/_components/ProjectCardsLoading.tsx b/src/app/(pages)/projects/_components/ProjectCardsLoading.tsx new file mode 100644 index 00000000..2bde7692 --- /dev/null +++ b/src/app/(pages)/projects/_components/ProjectCardsLoading.tsx @@ -0,0 +1,59 @@ +import { Card, CardHeader, CardTitle, CardContent, CardFooter } from '@/components/ui/card'; +import { Skeleton } from '@/components/ui/skeleton'; + +export default function ProjectCardSkeleton() { + return new Array(2).fill('').map(id => ( + <> + +
+ +
+ +
+ + + + +
+ +
+ +
+
+
+ + + + + + + +
+
+ + )); +} + +export function PastProjectCardSkeleton() { + return new Array(3).fill('').map(id => ( +
+
+
+ +
+
+
+ + +
+ + + +
+
+
+ )); +} diff --git a/src/app/(pages)/projects/page.tsx b/src/app/(pages)/projects/page.tsx index 28c50163..64fdd118 100644 --- a/src/app/(pages)/projects/page.tsx +++ b/src/app/(pages)/projects/page.tsx @@ -1,19 +1,29 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import CurrentProjects from './_components/CurrentProjects'; import PastProjects from './_components/PastProjects'; -import { getProjects, isCurrentProject } from '@/lib/notion/projects'; +// import { getProjects, isCurrentProject } from '@/lib/notion/projects'; +import BlockContainer from '@/components/BlockContainer'; +import ProjectCardSkeleton, { PastProjectCardSkeleton } from './_components/ProjectCardsLoading'; export const revalidate = Number(process.env.REVALIDATION_INTERVAL) || 3600; export default async function Projects() { - const res = await getProjects(); - const currentProjects = res.filter(project => isCurrentProject(project)); - const pastProjects = res.filter(project => !isCurrentProject(project)); - return (
- - + +
+ }> + + +
+
+ +
+ }> + + +
+
); } diff --git a/src/app/(pages)/students/_components/Section.tsx b/src/app/(pages)/students/_components/Section.tsx index 6ce995c2..f3b90774 100644 --- a/src/app/(pages)/students/_components/Section.tsx +++ b/src/app/(pages)/students/_components/Section.tsx @@ -19,8 +19,8 @@ export default function Section({ team }: { team: TeamDataType }) { titleSize="sm" >
- {team.teamMembers.map(person => ( - + {team.teamMembers.map(member => ( + ))}
diff --git a/src/app/(pages)/students/_components/Students.tsx b/src/app/(pages)/students/_components/Students.tsx new file mode 100644 index 00000000..6d6f7b81 --- /dev/null +++ b/src/app/(pages)/students/_components/Students.tsx @@ -0,0 +1,21 @@ +import { getStudents } from '@/lib/notion/students'; +import Section, { TeamDataType } from './Section'; +import { v4 as uuidv4 } from 'uuid'; + +export default async function Student() { + const students = await getStudents(); + + let teamNamesSet = new Set(); + for (const student of students) { + teamNamesSet.add(student.team); + } + + const teamNamesArray = Array.from(teamNamesSet); + const teams: TeamDataType[] = []; + for (const teamName of teamNamesArray) { + const teamMembers = students.filter(stu => stu.team == teamName); + teams.push({ teamName, teamMembers }); + } + + return teams.map(team =>
); +} diff --git a/src/app/(pages)/students/_components/StudentsLoading.tsx b/src/app/(pages)/students/_components/StudentsLoading.tsx new file mode 100644 index 00000000..f1af3e3c --- /dev/null +++ b/src/app/(pages)/students/_components/StudentsLoading.tsx @@ -0,0 +1,37 @@ +import BlockContainer from '@/components/BlockContainer'; +import { Skeleton } from '@/components/ui/skeleton'; + +export default function Loading() { + return ( +
+ + +
+ {new Array(12).fill('').map(id => ( + + ))} +
+
+ + +
+ {new Array(12).fill('').map(id => ( + + ))} +
+
+
+ ); +} + +function TeamProfileLoading() { + return ( +
+
+ +
+ + +
+ ); +} diff --git a/src/app/(pages)/students/_components/TeamProfile.tsx b/src/app/(pages)/students/_components/TeamProfile.tsx index e9919969..b6131709 100644 --- a/src/app/(pages)/students/_components/TeamProfile.tsx +++ b/src/app/(pages)/students/_components/TeamProfile.tsx @@ -15,7 +15,7 @@ function TeamProfileBase({ student, hover = false }: { student: StudentDataType; src={student.imageUrl} width={128} height={128} - alt={'Picture of ' + (hover ? student.name : 'blueprint logo')} + alt={'picture of' + (hover ? student.name : 'blueprint logo')} />

{student.name}

diff --git a/src/app/(pages)/students/page.tsx b/src/app/(pages)/students/page.tsx index 77cea84c..b6c41896 100644 --- a/src/app/(pages)/students/page.tsx +++ b/src/app/(pages)/students/page.tsx @@ -1,26 +1,10 @@ -import Section, { TeamDataType } from './_components/Section'; -import { getStudents } from '@/lib/notion/students'; -import { v4 as uuidv4 } from 'uuid'; import bluePeople from './_assets/blue_people.svg'; import Image from 'next/image'; - -export const revalidate = Number(process.env.REVALIDATION_INTERVAL) || 3600; +import Student from './_components/Students'; +import { Suspense } from 'react'; +import Loading from './_components/StudentsLoading'; export default async function Students() { - const students = await getStudents(); - - let teamNamesSet = new Set(); - for (const student of students) { - teamNamesSet.add(student.team); - } - - const teamNamesArray = Array.from(teamNamesSet); - const teams: TeamDataType[] = []; - for (const teamName of teamNamesArray) { - const teamMembers = students.filter(student => student.team == teamName); - teams.push({ teamName, teamMembers }); - } - return (
@@ -31,11 +15,11 @@ export default async function Students() { Image of blue figures
-
- {teams.map(team => ( -
- ))} -
+ }> +
+ +
+
diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx new file mode 100644 index 00000000..01b8b6d4 --- /dev/null +++ b/src/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
+ ) +} + +export { Skeleton }