Skip to content

Commit

Permalink
feat: badge commpteur actualites non lues
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurlbrjc committed Feb 24, 2025
1 parent 3e6e322 commit 90ea1f1
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 162 deletions.
4 changes: 2 additions & 2 deletions components/ActualitesModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function ActualitesModal({ onClose }: ActualitesModalProps) {
const modalRef = useRef<ModalHandles>(null)
const actualites = useActualites()

const aDesActualites = Boolean(actualites && actualites.articles.length > 0)
const aDesActualites = Boolean(actualites && actualites.length > 0)

const modalTemplate = (
<div className='rounded-l-l fixed right-0 bg-primary_lighten h-full max-w-[min(90%,_620px)] min-w-[min(30%)] overflow-auto pb-3 shadow-m'>
Expand Down Expand Up @@ -48,7 +48,7 @@ export default function ActualitesModal({ onClose }: ActualitesModalProps) {

{aDesActualites && (
<div className='p-6'>
{actualites?.articles.map((article) => (
{actualites?.map((article) => (
<article
className='bg-white px-4 py-2 rounded-base mb-4 [&_a]:underline [&_a]:text-primary [&_a]:hover:text-primary_darken [&_img]:max-w-[200px] [&_img]:my-4 [&_p]:text-grey_800'
key={article.id}
Expand Down
47 changes: 34 additions & 13 deletions components/NavLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import { DateTime } from 'luxon'
import { usePathname, useRouter } from 'next/navigation'
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'

import ActualitesModal from 'components/ActualitesModal'
import NavLink from 'components/ui/Form/NavLink'
import { IconName } from 'components/ui/IconComponent'
import {
aDeNouvellesActualites,
compterNouvellesActualites,
estSuperviseur,
utiliseChat,
} from 'interfaces/conseiller'
Expand Down Expand Up @@ -40,7 +40,7 @@ export default function NavLinks({
}: NavLinksProps) {
const router = useRouter()
const pathname = usePathname()
const [conseiller] = useConseiller()
const [conseiller, setConseiller] = useConseiller()
const [portefeuille] = usePortefeuille()
const actualites = useActualites()

Expand All @@ -58,6 +58,11 @@ export default function NavLinks({
? 'Une information en attente de mise à jour'
: undefined

const [countNouvellesActualites, setCountNouvellesActualites] =
useState<number>()
const [labelNouvellesActualites, setLabelNouvellesActualites] =
useState<string>()

function isCurrentRoute(href: string) {
return pathname.startsWith(href)
}
Expand Down Expand Up @@ -85,10 +90,33 @@ export default function NavLinks({

async function ouvrirActualites() {
setAfficherActualiteModal(true)
modifierDateVisionnageActus(DateTime.now())
const now = DateTime.now()
trackActualite()

modifierDateVisionnageActus(now)
setConseiller({ ...conseiller, dateVisionnageActus: now.toISO() })
}

useEffect(() => {
if (
!items.includes(NavItem.Actualites) ||
process.env.NEXT_PUBLIC_ENABLE_ACTUS !== 'true' ||
!actualites
)
return

const count = compterNouvellesActualites(
conseiller.dateVisionnageActus,
actualites
)
if (!count) return

setCountNouvellesActualites(count)
if (count > 1)
setLabelNouvellesActualites(' nouvelles actualités sont disponibles')
else setLabelNouvellesActualites(' nouvelle actualité est disponible')
}, [actualites, conseiller.dateVisionnageActus])

return (
<>
<ul>
Expand Down Expand Up @@ -216,15 +244,8 @@ export default function NavLinks({
className='break-all'
onClick={ouvrirActualites}
showLabelOnSmallScreen={showLabelsOnSmallScreen}
badgeLabel={
actualites &&
aDeNouvellesActualites(
conseiller,
actualites.dateDerniereModification
)
? 'De nouvelles actualités sont disponibles'
: undefined
}
badgeCount={countNouvellesActualites}
badgeLabel={labelNouvellesActualites}
/>
)}
</ul>
Expand Down
28 changes: 20 additions & 8 deletions components/ui/Form/NavLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type NavLinkProps = {
iconName: IconName
showLabelOnSmallScreen: boolean
badgeLabel?: string
badgeCount?: number
href?: string
isActive?: boolean
className?: string
Expand All @@ -21,6 +22,7 @@ export default function NavLink({
iconName,
className,
badgeLabel,
badgeCount,
showLabelOnSmallScreen = false,
onClick,
}: NavLinkProps) {
Expand Down Expand Up @@ -48,7 +50,8 @@ export default function NavLink({
>
{label}
</span>
{badgeLabel && <BadgeNavLink label={badgeLabel} />}

{badgeLabel && <BadgeNavLink label={badgeLabel} count={badgeCount} />}
</>
)
}
Expand All @@ -75,15 +78,24 @@ export default function NavLink({
)
}

function BadgeNavLink({ label }: { label: string }) {
function BadgeNavLink({ label, count }: { label: string; count?: number }) {
return (
<>
<IconComponent
focusable={false}
aria-hidden={true}
className='w-4 h-4 fill-warning absolute border border-white top-0 left-0 bg-white rounded-full'
name={IconName.Error}
/>
{!count && (
<IconComponent
focusable={false}
aria-hidden={true}
className='w-4 h-4 fill-warning absolute border border-white top-0 left-0 bg-white rounded-full'
name={IconName.Error}
/>
)}

{count && (
<span className='w-4 h-4 absolute top-0 left-0 rounded-full border border-white bg-warning text-white text-xs-bold !leading-none'>
{count}
</span>
)}

<span className='sr-only'>{label}</span>
</>
)
Expand Down
88 changes: 42 additions & 46 deletions fixtures/actualites.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,50 @@
import { ActualitesParsees, ActualitesRaw } from 'interfaces/actualites'

export function uneActualite(): ActualitesParsees {
return {
articles: [
{
id: 1,
titre: 'Invitation à la journée présentiel du 31 octobre 2024',
etiquettes: [{ couleur: 'primary', id: 7, nom: 'Primaire' }],
contenu: [
<p key={0}>Rdv demain aux nouveaux locaux de la Fabrique</p>,
<a
key={1}
href='perdu.com'
target='_blank'
rel='noreferrer noopener'
className='inline-flex items-center whitespace-nowrap underline'
aria-label='Vous êtes perdu ? (nouvelle fenêtre)'
return [
{
id: 1,
titre: 'Invitation à la journée présentiel du 31 octobre 2024',
etiquettes: [{ couleur: 'primary', id: 7, nom: 'Primaire' }],
contenu: [
<p key={0}>Rdv demain aux nouveaux locaux de la Fabrique</p>,
<a
key={1}
href='perdu.com'
target='_blank'
rel='noreferrer noopener'
className='inline-flex items-center whitespace-nowrap underline'
aria-label='Vous êtes perdu ? (nouvelle fenêtre)'
>
Vous êtes perdu ?
<svg
aria-hidden={true}
focusable={false}
viewBox='0 0 12 12'
className='ml-1 w-3 h-3'
xmlns='http://www.w3.org/2000/svg'
>
Vous êtes perdu ?
<svg
aria-hidden={true}
focusable={false}
viewBox='0 0 12 12'
className='ml-1 w-3 h-3'
xmlns='http://www.w3.org/2000/svg'
>
<path
d='M10 10.6667H2C1.63333 10.6667 1.33333 10.3667 1.33333 10V2C1.33333 1.63333 1.63333 1.33333 2 1.33333H5.33333C5.7 1.33333 6 1.03333 6 0.666667C6 0.3 5.7 0 5.33333 0H1.33333C0.593333 0 0 0.6 0 1.33333V10.6667C0 11.4 0.6 12 1.33333 12H10.6667C11.4 12 12 11.4 12 10.6667V6.66667C12 6.3 11.7 6 11.3333 6C10.9667 6 10.6667 6.3 10.6667 6.66667V10C10.6667 10.3667 10.3667 10.6667 10 10.6667ZM7.33333 0.666667C7.33333 1.03333 7.63333 1.33333 8 1.33333H9.72667L3.64 7.42C3.38 7.68 3.38 8.1 3.64 8.36C3.9 8.62 4.32 8.62 4.58 8.36L10.6667 2.27333V4C10.6667 4.36667 10.9667 4.66667 11.3333 4.66667C11.7 4.66667 12 4.36667 12 4V0H8C7.63333 0 7.33333 0.3 7.33333 0.666667Z'
fill='currentColor'
/>
</svg>
</a>,
],
},
],
dateDerniereModification: '2024-10-30',
}
<path
d='M10 10.6667H2C1.63333 10.6667 1.33333 10.3667 1.33333 10V2C1.33333 1.63333 1.63333 1.33333 2 1.33333H5.33333C5.7 1.33333 6 1.03333 6 0.666667C6 0.3 5.7 0 5.33333 0H1.33333C0.593333 0 0 0.6 0 1.33333V10.6667C0 11.4 0.6 12 1.33333 12H10.6667C11.4 12 12 11.4 12 10.6667V6.66667C12 6.3 11.7 6 11.3333 6C10.9667 6 10.6667 6.3 10.6667 6.66667V10C10.6667 10.3667 10.3667 10.6667 10 10.6667ZM7.33333 0.666667C7.33333 1.03333 7.63333 1.33333 8 1.33333H9.72667L3.64 7.42C3.38 7.68 3.38 8.1 3.64 8.36C3.9 8.62 4.32 8.62 4.58 8.36L10.6667 2.27333V4C10.6667 4.36667 10.9667 4.66667 11.3333 4.66667C11.7 4.66667 12 4.36667 12 4V0H8C7.63333 0 7.33333 0.3 7.33333 0.666667Z'
fill='currentColor'
/>
</svg>
</a>,
],
dateDerniereModification: '2024-10-30',
},
]
}

export function uneActualiteRaw(): ActualitesRaw {
return {
articles: [
{
id: 1,
titre: 'Invitation à la journée présentiel du 31 octobre 2024',
etiquettes: [],
contenu:
'<p /><p>Rdv demain aux nouveaux locaux de la Fabrique</p> <p/><a href="perdu.com">Vous êtes perdu ?</a><p></p>',
},
],
dateDerniereModification: '2024-10-30',
}
return [
{
id: 1,
titre: 'Invitation à la journée présentiel du 31 octobre 2024',
etiquettes: [],
contenu:
'<p /><p>Rdv demain aux nouveaux locaux de la Fabrique</p> <p/><a href="perdu.com">Vous êtes perdu ?</a><p></p>',
dateDerniereModification: '2024-10-30',
},
]
}
28 changes: 12 additions & 16 deletions interfaces/actualites.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { domToReact } from 'html-react-parser'

export type ActualitesRaw = {
articles: Array<{
id: number
titre: string
etiquettes: EtiquetteArticle[]
contenu: string
}>
export type ActualitesRaw = Array<{
id: number
titre: string
etiquettes: EtiquetteArticle[]
contenu: string
dateDerniereModification: string
}
}>

export type ActualitesParsees = {
articles: Array<{
id: number
titre: ReturnType<typeof domToReact>
etiquettes: EtiquetteArticle[]
contenu: ReturnType<typeof domToReact>
}>
export type ActualitesParsees = Array<{
id: number
titre: ReturnType<typeof domToReact>
etiquettes: EtiquetteArticle[]
contenu: ReturnType<typeof domToReact>
dateDerniereModification: string
}
}>

export type ArticleJson = {
id: number
Expand Down
22 changes: 12 additions & 10 deletions interfaces/conseiller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DateTime } from 'luxon'
import { Session } from 'next-auth'

import { ActualitesParsees } from 'interfaces/actualites'
import { MissionLocale } from 'interfaces/referentiel'
import {
estMilo,
Expand Down Expand Up @@ -86,14 +87,15 @@ export function doitSignerLesCGU(conseiller: Conseiller): boolean {
DateTime.fromISO(process.env.VERSION_CGU_CEJ_COURANTE!)
}

export function aDeNouvellesActualites(
{ dateVisionnageActus }: Conseiller,
dernierePublication: string
): boolean {
if (!dateVisionnageActus) return true

return (
DateTime.fromISO(dateVisionnageActus) <
DateTime.fromISO(dernierePublication)
)
export function compterNouvellesActualites(
dateVisionnageActus: string | undefined,
actualites: ActualitesParsees
): number {
if (!dateVisionnageActus) return actualites.length

return actualites.filter(
({ dateDerniereModification }) =>
DateTime.fromISO(dateVisionnageActus) <
DateTime.fromISO(dateDerniereModification)
).length
}
13 changes: 6 additions & 7 deletions services/actualites.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
EtiquetteArticle,
TagJson,
} from 'interfaces/actualites'
import { Structure, structureMilo } from 'interfaces/structure'
import { Structure } from 'interfaces/structure'
import { fetchJson } from 'utils/httpClient'

export async function getActualites(
Expand All @@ -22,16 +22,15 @@ export async function getActualites(
] = await Promise.all([fetchJson(urlTags), fetchJson(urlActualites)])
if (!articlesJson.length) return

const articlesTries = [...articlesJson].sort(comparerArticles)
return {
articles: articlesTries.map((article: ArticleJson) => ({
return [...articlesJson]
.sort(comparerArticles)
.map((article: ArticleJson) => ({
id: article.id,
titre: article.title.rendered,
etiquettes: extraireEtiquettes(article, tagsJson),
contenu: extraireContenuAssaini(article),
})),
dateDerniereModification: articlesTries[0].modified,
}
dateDerniereModification: article.modified,
}))
}

function comparerArticles(a1: ArticleJson, a2: ArticleJson) {
Expand Down
Loading

0 comments on commit 90ea1f1

Please sign in to comment.