Skip to content

Commit

Permalink
feat: commenter action
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurlbrjc committed Nov 27, 2024
1 parent 190b519 commit 69455ee
Show file tree
Hide file tree
Showing 20 changed files with 645 additions and 201 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { DateTime } from 'luxon'
import { useRouter } from 'next/navigation'
import React, { useRef, useState } from 'react'

import { HistoriqueAction } from 'components/action/HistoriqueAction'
import CommentaireAction from 'components/action/CommentaireAction'
import HistoriqueAction from 'components/action/HistoriqueAction'
import StatutActionForm from 'components/action/StatutActionForm'
import Modal, { ModalHandles } from 'components/Modal'
import PageActionsPortal from 'components/PageActionsPortal'
Expand Down Expand Up @@ -242,6 +243,8 @@ function DetailActionPage({
</dl>
</div>

<CommentaireAction action={action} beneficiaire={jeune} />

<HistoriqueAction action={action} />

{showSuppression && (
Expand Down
128 changes: 98 additions & 30 deletions clients/firebase.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import {
import { DateTime } from 'luxon'

import { apiGet } from 'clients/api.client'
import { Chat } from 'interfaces/beneficiaire'
import { Action } from 'interfaces/action'
import { BeneficiaireEtChat, Chat } from 'interfaces/beneficiaire'
import { UserType } from 'interfaces/conseiller'
import { InfoFichier } from 'interfaces/fichier'
import {
Expand All @@ -51,6 +52,7 @@ type TypeMessageFirebase =
| 'MESSAGE_EVENEMENT'
| 'MESSAGE_EVENEMENT_EMPLOI'
| 'MESSAGE_SESSION_MILO'
| 'MESSAGE_ACTION'
| 'NOUVEAU_CONSEILLER_TEMPORAIRE'

export type FirebaseMessage = {
Expand All @@ -63,6 +65,7 @@ export type FirebaseMessage = {
type: TypeMessageFirebase | undefined
status?: string
offre?: InfoOffreFirebase
action?: InfoActionFirebase
evenement?: EvenementPartage
evenementEmploi?: EvenementEmploi
sessionMilo?: SessionMilo
Expand Down Expand Up @@ -98,6 +101,11 @@ export type InfoOffreFirebase = {
type?: string
}

export type InfoActionFirebase = {
id: string
titre: string
}

export interface EvenementPartage {
id: string
titre: string
Expand All @@ -123,7 +131,7 @@ type BaseCreateFirebaseMessage = {
date: DateTime
}

type BaseCreateFirebaseMessageImportant = {
type CreateFirebaseMessageImportant = {
idConseiller: string
dateDebut: DateTime
dateFin: DateTime
Expand All @@ -134,10 +142,15 @@ type BaseCreateFirebaseMessageImportant = {
export type CreateFirebaseMessage = BaseCreateFirebaseMessage & {
infoPieceJointe?: InfoFichier
}
export type CreateFirebaseMessageWithOffre = BaseCreateFirebaseMessage & {
export type CreateFirebaseMessagePartageOffre = BaseCreateFirebaseMessage & {
offre: BaseOffre
}

export type CreateFirebaseMessageCommentaireAction =
BaseCreateFirebaseMessage & {
action: Action
}

type UpdateFirebaseMessage = {
message: string
date: DateTime
Expand Down Expand Up @@ -186,7 +199,7 @@ export async function addMessage(
}

export async function addMessageImportant(
data: BaseCreateFirebaseMessageImportant
data: CreateFirebaseMessageImportant
): Promise<string> {
const firebaseMessage = createFirebaseMessageImportant(data)

Expand Down Expand Up @@ -359,6 +372,35 @@ export async function getChatsDuConseiller(
}
}

export async function getChatDuBeneficiaire(
idConseiller: string,
idBeneficiaire: string
): Promise<Chat | undefined> {
try {
const collectionRef = collection(
getDb(),
chatCollection
) as CollectionReference<FirebaseChat, FirebaseChat>

const querySnapshots: QuerySnapshot<FirebaseChat, FirebaseChat> =
await getDocs(
query<FirebaseChat, FirebaseChat>(
collectionRef,
where('conseillerId', '==', idConseiller),
where('jeuneId', '==', idBeneficiaire)
)
)
if (querySnapshots.empty) return

const document = querySnapshots.docs[0]
return chatFromFirebase(document.id, document.data())
} catch (e) {
console.error(e)
captureError(e as Error)
throw e
}
}

export async function getMessagesGroupe(
idConseiller: string,
idGroupe: string
Expand Down Expand Up @@ -413,22 +455,24 @@ export function observeChat(
}

export function observeDerniersMessagesDuChat(
idChat: string,
beneficiaireEtChat: BeneficiaireEtChat,
nbMessages: number,
onMessagesAntechronologiques: (messages: Message[]) => void
): () => void {
try {
return onSnapshot<FirebaseMessage, FirebaseMessage>(
query<FirebaseMessage, FirebaseMessage>(
collection(getChatReference(idChat), 'messages') as CollectionReference<
FirebaseMessage,
FirebaseMessage
>,
collection(
getChatReference(beneficiaireEtChat.chatId),
'messages'
) as CollectionReference<FirebaseMessage, FirebaseMessage>,
orderBy('creationDate', 'desc'),
limit(nbMessages)
),
(querySnapshot: QuerySnapshot<FirebaseMessage, FirebaseMessage>) => {
const messages: Message[] = querySnapshot.docs.map(docSnapshotToMessage)
const messages: Message[] = querySnapshot.docs.map((doc) =>
docSnapshotToMessage(doc, beneficiaireEtChat.id)
)
if (messages.length && !messages.at(-1)!.creationDate) {
return
}
Expand All @@ -443,12 +487,9 @@ export function observeDerniersMessagesDuChat(
}
}

export async function getMessageImportantSnapshot(
export async function findMessageImportant(
idConseiller: string
): Promise<
| DocumentSnapshot<FirebaseMessageImportant, FirebaseMessageImportant>
| undefined
> {
): Promise<(FirebaseMessageImportant & { id: string }) | undefined> {
const collectionRef = collection(
getDb(),
messageImportantCollection
Expand All @@ -464,7 +505,10 @@ export async function getMessageImportantSnapshot(
)
)

if (querySnapshots.docs.length > 0) return querySnapshots.docs[0]
if (!querySnapshots.empty) {
const document = querySnapshots.docs[0]
return { ...document.data(), id: document.id }
}
}

export async function rechercherMessages(
Expand Down Expand Up @@ -497,18 +541,19 @@ export async function rechercherMessages(
message.creationDate._seconds * 1000
),
},
id
id,
idBeneficiaire
),
}
})
}

export async function getMessagesPeriode(
idChat: string,
beneficiaireEtChat: BeneficiaireEtChat,
debut: DateTime,
fin: DateTime
): Promise<Message[]> {
const chatRef = getChatReference(idChat)
const chatRef = getChatReference(beneficiaireEtChat.chatId)
const querySnapshots: QuerySnapshot<FirebaseMessage, FirebaseMessage> =
await getDocs(
query<FirebaseMessage, FirebaseMessage>(
Expand All @@ -522,7 +567,9 @@ export async function getMessagesPeriode(
)
)

return querySnapshots.docs.map(docSnapshotToMessage)
return querySnapshots.docs.map((doc) =>
docSnapshotToMessage(doc, beneficiaireEtChat.id)
)
}

function retrieveApp() {
Expand Down Expand Up @@ -560,7 +607,7 @@ async function getGroupeSnapshot(
)
)

if (querySnapshots.docs.length > 0) return querySnapshots.docs[0]
if (!querySnapshots.empty) return querySnapshots.docs[0]
}

async function getChatsSnapshot(
Expand Down Expand Up @@ -623,7 +670,10 @@ function getMessageReference(
}

function createFirebaseMessage(
data: CreateFirebaseMessage | CreateFirebaseMessageWithOffre
data:
| CreateFirebaseMessage
| CreateFirebaseMessagePartageOffre
| CreateFirebaseMessageCommentaireAction
): FirebaseMessage {
const type: TypeMessage = TypeMessage.MESSAGE
let { encryptedText, iv } = data.message
Expand All @@ -649,26 +699,31 @@ function createFirebaseMessage(
id,
titre,
type: typeOffre,
} = (data as CreateFirebaseMessageWithOffre).offre
} = (data as CreateFirebaseMessagePartageOffre).offre
firebaseMessage.offre = { id, titre, type: typeToFirebase(typeOffre) }
}

if (Object.prototype.hasOwnProperty.call(data, 'action')) {
firebaseMessage.type = TypeMessage.MESSAGE_ACTION
const { id, titre } = (data as CreateFirebaseMessageCommentaireAction)
.action
firebaseMessage.action = { id, titre }
}

return firebaseMessage
}

function createFirebaseMessageImportant(
data: BaseCreateFirebaseMessageImportant
data: CreateFirebaseMessageImportant
): FirebaseMessageImportant {
let { encryptedText, iv } = data.message
const firebaseMessage: FirebaseMessageImportant = {
return {
content: encryptedText,
iv,
idConseiller: data.idConseiller,
dateDebut: toTimestamp(data.dateDebut),
dateFin: toTimestamp(data.dateFin),
}

return firebaseMessage
}

type FirebaseChat = {
Expand Down Expand Up @@ -763,10 +818,15 @@ export function chatToFirebase(chat: Partial<Chat>): Partial<FirebaseChat> {
}

export function docSnapshotToMessage(
docSnapshot: QueryDocumentSnapshot<FirebaseMessage>
docSnapshot: QueryDocumentSnapshot<FirebaseMessage>,
idBeneficiaire: string
): Message {
const firebaseMessage = docSnapshot.data()
return firebaseMessageToMessage(firebaseMessage, docSnapshot.id)
return firebaseMessageToMessage(
firebaseMessage,
docSnapshot.id,
idBeneficiaire
)
}

function chatFromFirebase(chatId: string, firebaseChat: FirebaseChat): Chat {
Expand All @@ -792,10 +852,12 @@ function chatFromFirebase(chatId: string, firebaseChat: FirebaseChat): Chat {

function firebaseMessageToMessage(
firebaseMessage: FirebaseMessage,
id: string
id: string,
idBeneficiaire: string
): Message {
const message: Message = {
id,
idBeneficiaire,
sentBy: firebaseMessage.sentBy,
content: firebaseMessage.content,
iv: firebaseMessage.iv,
Expand All @@ -813,6 +875,10 @@ function firebaseMessageToMessage(
message.infoOffre = offreFromFirebase(firebaseMessage.offre)
}

if (message.type === TypeMessage.MESSAGE_ACTION && firebaseMessage.action) {
message.infoAction = firebaseMessage.action
}

if (
message.type === TypeMessage.MESSAGE_EVENEMENT &&
firebaseMessage.evenement
Expand Down Expand Up @@ -879,6 +945,8 @@ function firebaseToMessageType(
return TypeMessage.MESSAGE_PJ
case 'MESSAGE_OFFRE':
return TypeMessage.MESSAGE_OFFRE
case 'MESSAGE_ACTION':
return TypeMessage.MESSAGE_ACTION
case 'MESSAGE_EVENEMENT':
return TypeMessage.MESSAGE_EVENEMENT
case 'MESSAGE_EVENEMENT_EMPLOI':
Expand Down
62 changes: 62 additions & 0 deletions components/Details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, {
ForwardedRef,
forwardRef,
ReactNode,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react'

import IconComponent, { IconName } from 'components/ui/IconComponent'

interface DetailsProps {
summary: string
children: ReactNode
}

function Details(
{ summary, children }: DetailsProps,
ref: ForwardedRef<{ focusSummary: () => void }>
) {
const detailsRef = useRef<HTMLDetailsElement>(null)
useImperativeHandle(ref, () => ({
focusSummary: () => detailsRef.current!.querySelector('summary')!.focus(),
}))

const [expanded, setExpanded] = useState<boolean>()

useEffect(() => {
function toggleExpanded() {
setExpanded(detailsRef.current!.open)
}

const detailsNode = detailsRef.current!
detailsNode.addEventListener('toggle', toggleExpanded)
return () => detailsNode.removeEventListener('toggle', toggleExpanded)
}, [])

return (
<details
ref={detailsRef}
className='bg-primary_lighten p-6 mt-8 rounded-base shadow-base'
>
<summary
className={`text-m-bold text-primary relative flex justify-between items-center cursor-pointer ${expanded ? 'mb-5' : ''}`}
title={`${expanded ? 'Cacher' : 'Voir'} ${summary}`}
>
{summary}
<IconComponent
name={expanded ? IconName.ChevronUp : IconName.ChevronDown}
className='h-6 w-6 fill-current'
focusable={false}
aria-hidden={true}
/>
</summary>

{children}
</details>
)
}

export default forwardRef(Details)
Loading

0 comments on commit 69455ee

Please sign in to comment.