Skip to content

Commit

Permalink
feat: show conversations (#60)
Browse files Browse the repository at this point in the history
* feat: add autoscroll on assistant or exchange creation

* feat: add types

* feat: add tabular view of conversations

Co-authored-by: deRohrer <[email protected]>
  • Loading branch information
juancarlosfarah and deRohrer authored Sep 3, 2024
1 parent ede15e1 commit 6ff29d1
Show file tree
Hide file tree
Showing 15 changed files with 673 additions and 297 deletions.
2 changes: 1 addition & 1 deletion src/config/appSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { UUID } from '@graasp/sdk';

import Agent from '@/types/Agent';

type AssistantSettings = Omit<Agent, 'type'>;
export type AssistantSettings = Omit<Agent, 'type'>;

export type AssistantsSettingsType = {
assistantList: AssistantSettings[];
Expand Down
9 changes: 0 additions & 9 deletions src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { Member } from '@graasp/sdk';

import { t } from 'i18next';
import { v4 as uuidv4 } from 'uuid';

import { defaultSettingsValues } from '@/modules/context/SettingsContext';
Expand Down Expand Up @@ -53,9 +50,3 @@ export const defaultExchange: Exchange = {
createdAt: new Date(),
updatedAt: new Date(),
};

export const placeholderMember: Member = {
id: '',
name: t('CONVERSATIONS.PLACEHOLDER'),
email: '',
};
15 changes: 10 additions & 5 deletions src/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,16 @@
},
"CONVERSATIONS": {
"TITLE": "View Conversations",
"MEMBER": "Please select a member",
"PLACEHOLDER": "Please select a member",
"NONE": "No conversations so far.",
"COMPLETE": "Completed",
"INCOMPLETE": "Not completed",
"TABLE": {
"MEMBER": "Member",
"UPDATED": "Last change",
"STATUS": "Status",
"NOT_STARTED": "Not started",
"COMPLETE": "Completed",
"INCOMPLETE": "Not completed",
"DELETE": "Delete interaction",
"NONE": "No conversations so far."
},
"RESET": "Delete and reset conversation"
},
"START": "Start",
Expand Down
15 changes: 10 additions & 5 deletions src/langs/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,16 @@
},
"CONVERSATIONS": {
"TITLE": "Voir les Conversations",
"MEMBER": "Veuillez sélectionner un membre",
"PLACEHOLDER": "Veuillez sélectionner un membre",
"NONE": "Aucune conversation jusqu'à présent.",
"COMPLETE": "Terminé",
"INCOMPLETE": "Pas terminé",
"TABLE": {
"MEMBER": "Membre",
"UPDATED": "Dernière modification",
"STATUS": "Statut",
"NOT_STARTED": "Non démarré",
"COMPLETE": "Completed",
"INCOMPLETE": "Non terminé",
"DELETE": "Supprimer l'interaction",
"NONE": "Aucune conversation jusqu'à présent"
},
"RESET": "Supprimer et réinitialiser la conversation"
},
"START": "Démarrer",
Expand Down
1 change: 1 addition & 0 deletions src/modules/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const theme = createTheme({
default: grey['500'],
background: {
paper: '#fff',
default: '#fafaff', // Default background for the app
},
},
status: {
Expand Down
63 changes: 37 additions & 26 deletions src/modules/interaction/ParticipantInteraction.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import {
Dispatch,
MutableRefObject,
ReactElement,
SetStateAction,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { useTranslation } from 'react-i18next';
import { UseTranslationResponse, useTranslation } from 'react-i18next';

import { Button } from '@mui/material';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';

import { useLocalContext } from '@graasp/apps-query-client';
import { LocalContext, useLocalContext } from '@graasp/apps-query-client';

import {
defaultAssistant,
Expand All @@ -28,19 +31,20 @@ import AgentType from '@/types/AgentType';
import Exchange from '@/types/Exchange';
import Interaction from '@/types/Interaction';

import { useSettings } from '../context/SettingsContext';
import { SettingsContextType, useSettings } from '../context/SettingsContext';

// Main component: ParticipantInteraction
const ParticipantInteraction = (): ReactElement => {
// Getting the participant ID from local context
const { memberId: participantId } = useLocalContext();
const { memberId: participantId }: LocalContext = useLocalContext();

const { data: appDatas } = hooks.useAppData<Interaction>();
const { mutate: postAppData } = mutations.usePostAppData();
const { mutate: patchAppData } = mutations.usePatchAppData();
const { chat, exchanges } = useSettings();
const { chat, exchanges }: SettingsContextType = useSettings();

const { t } = useTranslation();
const { t }: UseTranslationResponse<'translations', undefined> =
useTranslation();

// Define the current member as an agent, merging with the default user
const currentMember: Agent = {
Expand Down Expand Up @@ -89,23 +93,26 @@ const ParticipantInteraction = (): ReactElement => {
);

// Ref to track if the app data has already been posted
const hasPosted = useRef(!!currentAppData);
const hasPosted: MutableRefObject<boolean> = useRef(!!currentAppData);

// State to manage the current interaction, either from existing data or a new template
const [interaction, setInteraction] = useState<Interaction>(
const [interaction, setInteraction]: [
Interaction,
Dispatch<SetStateAction<Interaction>>,
] = useState<Interaction>(
(currentAppData?.data as Interaction) || createInteractionFromTemplate(),
);

// Effect to post the interaction data if it hasn't been posted yet
useEffect(() => {
useEffect((): void => {
if (!hasPosted.current) {
postAppData({ data: interaction, type: 'Interaction' });
hasPosted.current = true;
}
}, [interaction, postAppData]);

// Effect to patch the interaction data if it has been posted and current app data exists
useEffect(() => {
useEffect((): void => {
if (hasPosted.current && currentAppData?.id) {
patchAppData({
id: currentAppData.id,
Expand All @@ -116,14 +123,16 @@ const ParticipantInteraction = (): ReactElement => {

// Callback to update a specific exchange within the interaction
const updateExchange = useCallback((updatedExchange: Exchange): void => {
setInteraction((prevState) => ({
...prevState,
exchanges: {
exchangeList: prevState.exchanges.exchangeList.map((exchange) =>
exchange.id === updatedExchange.id ? updatedExchange : exchange,
),
},
}));
setInteraction(
(prevState: Interaction): Interaction => ({
...prevState,
exchanges: {
exchangeList: prevState.exchanges.exchangeList.map((exchange) =>
exchange.id === updatedExchange.id ? updatedExchange : exchange,
),
},
}),
);
}, []);

// Effect to handle actions when the user tries to leave the page (before unload)
Expand All @@ -147,17 +156,19 @@ const ParticipantInteraction = (): ReactElement => {

// Function to start the interaction
const startInteraction = (): void => {
setInteraction((prev) => ({
...prev,
started: true,
startedAt: new Date(),
}));
setInteraction(
(prev: Interaction): Interaction => ({
...prev,
started: true,
startedAt: new Date(),
}),
);
};

// Function to move to the next exchange or complete the interaction
const goToNextExchange = (): void => {
setInteraction((prev) => {
const numExchanges = prev.exchanges.exchangeList.length;
setInteraction((prev: Interaction): Interaction => {
const numExchanges: number = prev.exchanges.exchangeList.length;
if (prev.currentExchange === numExchanges - 1) {
// If this is the last exchange, mark the interaction as completed
return {
Expand All @@ -180,7 +191,7 @@ const ParticipantInteraction = (): ReactElement => {
}

// Handle the start of the interaction
const handleStartInteraction = (): void => {
const handleStartInteraction: () => void = (): void => {
startInteraction();
};

Expand Down
Loading

0 comments on commit 6ff29d1

Please sign in to comment.