Skip to content

Commit

Permalink
sortable references
Browse files Browse the repository at this point in the history
  • Loading branch information
cooperlarson committed Oct 7, 2024
1 parent b0c0290 commit c684720
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 16 deletions.
35 changes: 35 additions & 0 deletions src/app/_blocks/References/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,41 @@
position: relative;
}

.sortSelector {
font-size: 24px;
margin-bottom: 20px;
display: flex;
align-items: center;

label {
padding-right: 10px;
font-weight: 500;
color: #333;
}

select {
font-size: 18px;
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f9f9f9;
color: #333;
outline: none;
cursor: pointer;
transition: all 0.3s ease;

&:hover, &:focus {
border-color: #007bff;
background-color: #fff;
box-shadow: 0 0 8px rgba(0, 123, 255, 0.2);
}

&:active {
background-color: #e6f0ff;
}
}
}

.introContent {
margin-bottom: calc(var(--base) * 2);

Expand Down
86 changes: 74 additions & 12 deletions src/app/_blocks/References/index.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,87 @@
'use client'

import React, { useEffect, useState } from 'react'
import React, { useEffect, useMemo, useState } from 'react'

import { Reference } from '../../../payload/payload-types'
import { fetchDocs } from '../../_api/fetchDocs'
import { Gutter } from '../../_components/Gutter'
import { REFERENCES } from '../../_graphql/references'
import { ReferenceHero } from '../../_heros/ReferenceHero'
import type { ReferenceBlockProps } from './types'

import classes from './index.module.scss'

export const ReferencesBlock: React.FC<ReferenceBlockProps & { id?: string }> = props => {
const { id } = props
const calculateExtremeDate = references => {
if (!references || references.length === 0) return null

const [references, setReferences] = useState<Reference[]>([])
// Flatten all dates from reviews (both date and endDate)
const dates = references
.flatMap(ref => [ref.date, ref.endDate].filter(Boolean)) // Remove null/undefined values
.map(dateString => new Date(dateString)) // Convert to Date objects
.filter(date => !isNaN(date.getTime())) // Filter out invalid dates

if (dates.length === 0) return null

// Return the oldest date for sorting purposes (regardless of the sort order)
return new Date(Math.min(...dates.map(date => date.getTime())))
}

export const ReferencesBlock: React.FC<{ id?: string }> = ({ id }) => {
const [references, setReferences] = useState([])
const [isLoading, setIsLoading] = useState<boolean>(true)
const [error, setError] = useState<string | null>(null)
const [sortOrder, setSortOrder] = useState<'ascending' | 'descending'>('ascending')

// Fetch references on mount
useEffect(() => {
const fetchReferences = async () => {
setIsLoading(true)
setError(null)

try {
const fetchedReferences = await fetchDocs<Reference>('references')
const variables = { limit: 500 }
const response = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: REFERENCES,
variables,
}),
})

const result = await response.json()

if (result.errors) throw new Error('Failed to fetch references')

const fetchedReferences = result.data.References.docs.map(reference => ({
...reference,
extremeDate: calculateExtremeDate(reference.references), // Precalculate the extreme date
}))

setReferences(fetchedReferences)
setIsLoading(false)
} catch (err) {
setError('Failed to load references.')
} finally {
setIsLoading(false)
}
}

fetchReferences()
}, [])
}, []) // Run only once on mount

// Sort references based on the selected sort order
const sortedReferences = useMemo(() => {
return [...references].sort((a, b) => {
const aDate = a.extremeDate
const bDate = b.extremeDate

if (!aDate && !bDate) return 0
if (!aDate) return sortOrder === 'ascending' ? 1 : -1
if (!bDate) return sortOrder === 'ascending' ? -1 : 1

return sortOrder === 'ascending'
? aDate.getTime() - bDate.getTime()
: bDate.getTime() - aDate.getTime()
})
}, [references, sortOrder])

if (isLoading) {
return <Gutter>Loading...</Gutter>
Expand All @@ -44,8 +94,20 @@ export const ReferencesBlock: React.FC<ReferenceBlockProps & { id?: string }> =
return (
<div id={`block-${id}`} className={classes.archiveBlock}>
<Gutter>
<div className={classes.sortSelector}>
<label htmlFor="sortOrder">Sort by:</label>
<select
id="sortOrder"
value={sortOrder}
onChange={e => setSortOrder(e.target.value as 'ascending' | 'descending')}
>
<option value="ascending">Oldest First</option>
<option value="descending">Newest First</option>
</select>
</div>

<div className={classes.grid}>
{references.map((reference, index) => (
{sortedReferences.map((reference, index) => (
<ReferenceHero key={index} reference={reference} />
))}
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/app/_graphql/references.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { MEDIA } from './media'

export const REFERENCES = `
query References {
References(limit: 500) {
query References($limit: Int, $sort: String) {
References(limit: $limit, sort: $sort) {
docs {
slug
id
slug
title
references {
location
Expand Down
2 changes: 1 addition & 1 deletion src/app/_heros/ReferenceHero/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
rgba(0, 0, 0, 0.1) 1px 1px 4px; /* Sharper, defined shadow for clear separation */

img {
position: inherit !important;
position: relative !important;
object-fit: cover;
width: auto;
height: 300px !important;
Expand Down

0 comments on commit c684720

Please sign in to comment.