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
12 changes: 11 additions & 1 deletion components/clubs/ClubDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
import { BLOCKS, type TopLevelBlock } from '@contentful/rich-text-types';
import { ArrowLeft, ArrowUpRight } from 'lucide-react';
Expand All @@ -11,7 +12,8 @@
import ClubLogo from './ClubLogo';

import { useStore } from '@/store/useStore';
import { Fragment, useEffect } from 'react';
import { Fragment, useEffect, type MouseEvent } from 'react';
import { readClubsReturn } from '@/lib/clubs-return';

interface ClubDetailProps {
club: ClubItems;
Expand Down Expand Up @@ -62,7 +64,7 @@
const image = contentfulImage(items[0].url, { intrinsicWidth: items[0].width, intrinsicHeight: items[0].height });
return (
<figure className="my-8 w-full max-w-2xl mx-auto">
<img

Check warning on line 67 in components/clubs/ClubDetail.tsx

View workflow job for this annotation

GitHub Actions / build-app

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
src={image.src}
srcSet={image.srcSet || undefined}
sizes="(max-width: 768px) 100vw, 672px"
Expand Down Expand Up @@ -98,7 +100,7 @@
return (
<figure key={asset.sys.id} className="group">
<div className="overflow-hidden rounded-2xl bg-gray-100 shadow-sm">
<img

Check warning on line 103 in components/clubs/ClubDetail.tsx

View workflow job for this annotation

GitHub Actions / build-app

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
src={image.src}
srcSet={image.srcSet || undefined}
sizes={people ? '(max-width: 640px) 50vw, 240px' : '(max-width: 640px) 100vw, 360px'}
Expand Down Expand Up @@ -162,13 +164,20 @@
const ClubDetail: React.FC<ClubDetailProps> = ({ club }) => {
const { clubName, clubLogo, clubType, clubLink, description, isActivelyRecruitingMembers, aboutclub, sys } = club;
const { addToRecentlyViewed } = useStore();
const router = useRouter();

useEffect(() => {
if (club && sys.id) {
addToRecentlyViewed(`/clubs/${sys.id}`);
}
}, [club, sys.id, addToRecentlyViewed]);

const backToClubs = (event: MouseEvent<HTMLAnchorElement>) => {
if (readClubsReturn()?.clubId !== sys.id) return;
event.preventDefault();
router.back();
};

const assets = aboutclub?.links?.assets?.block ?? [];
const options = proseRichTextOptions(assets);
const findAsset = (id: string) => assets.find((asset) => asset.sys.id === id);
Expand All @@ -180,6 +189,7 @@
<div className="py-6 sm:py-10">
<Link
href="/clubs"
onClick={backToClubs}
className="inline-flex items-center gap-2 text-sm text-gray-500 hover:text-gray-900 transition-colors"
>
<ArrowLeft className="w-4 h-4" />
Expand Down
27 changes: 24 additions & 3 deletions components/clubs/ClubsList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import Container from '@/components/custom/Container';
import { Search } from 'lucide-react';
import Image from 'next/image';
Expand All @@ -15,6 +15,7 @@ import EmptyState from '@/components/events/EmptyState';
import { Users } from 'lucide-react';

import { CLUB_TYPES, matchesClubType } from '@/lib/data/taxonomy'
import { clearClubsReturn, readClubsReturn, rememberClubsReturn } from '@/lib/clubs-return'
interface ClubsListProps {
clubs: ClubItems[];
}
Expand All @@ -29,6 +30,26 @@ const ClubsList = ({ clubs }: ClubsListProps) => {
]

const [filteredClubs, setFilteredClubs] = useState<ClubItems[]>(clubs || []);
const pendingScroll = useRef<number | null>(null);

useEffect(() => {
const saved = readClubsReturn();
clearClubsReturn();
if (!saved) return;
pendingScroll.current = saved.scrollY;
setCurrentId(saved.tab);
setSearch(saved.search);
}, []);

useEffect(() => {
if (pendingScroll.current === null) return;
const y = pendingScroll.current;
pendingScroll.current = null;
requestAnimationFrame(() => window.scrollTo({ top: y, behavior: 'instant' }));
}, [filteredClubs]);

const openClub = (clubId: string) =>
rememberClubsReturn({ clubId, scrollY: window.scrollY, tab: currentId, search });

useEffect(() => {
let result = clubs || [];
Expand Down Expand Up @@ -100,7 +121,7 @@ const ClubsList = ({ clubs }: ClubsListProps) => {

<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 py-6'>
{filteredClubs.filter((club) => club.isFeatured)?.map((club, index) => (
<Link href={`/clubs/${club.sys.id}`} key={index} className='p-6 shadow-lg rounded-xl h-[454px] flex flex-col justify-between'>
<Link href={`/clubs/${club.sys.id}`} key={index} onClick={() => openClub(club.sys.id)} className='p-6 shadow-lg rounded-xl h-[454px] flex flex-col justify-between'>
<ClubLogo
name={club.clubName}
url={club.clubLogo?.url}
Expand Down Expand Up @@ -137,7 +158,7 @@ const ClubsList = ({ clubs }: ClubsListProps) => {
<h2 className='font-bold text-2xl font-header mb-8 text-gray-900'>Other Communities</h2>
<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-6 py-12'>
{filteredClubs?.filter(club => !club.isFeatured).map((club, index) => (
<Link href={`/clubs/${club.sys.id}`} key={index} className='bg-[#F9FAFB] p-6 rounded-xl flex flex-col gap-4 w-full'>
<Link href={`/clubs/${club.sys.id}`} key={index} onClick={() => openClub(club.sys.id)} className='bg-[#F9FAFB] p-6 rounded-xl flex flex-col gap-4 w-full'>
<div className='w-12 h-12 rounded-full bg-primary/13 p-1 flex items-center justify-center'>
<Image src={getClubIcon(club.clubType)} alt="" width={32} height={32} />
</div>
Expand Down
33 changes: 33 additions & 0 deletions lib/clubs-return.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const KEY = "clubs-return";
const MAX_AGE_MS = 30 * 60 * 1000;

export interface ClubsReturn {
clubId: string;
scrollY: number;
tab: number;
search: string;
at: number;
}

export function rememberClubsReturn(value: Omit<ClubsReturn, "at">) {
try {
sessionStorage.setItem(KEY, JSON.stringify({ ...value, at: Date.now() }));
} catch {}
}

export function readClubsReturn(): ClubsReturn | null {
try {
const raw = sessionStorage.getItem(KEY);
if (!raw) return null;
const value = JSON.parse(raw) as ClubsReturn;
return Date.now() - value.at < MAX_AGE_MS ? value : null;
} catch {
return null;
}
}

export function clearClubsReturn() {
try {
sessionStorage.removeItem(KEY);
} catch {}
}
Loading