Skip to content

Commit

Permalink
final messages
Browse files Browse the repository at this point in the history
  • Loading branch information
IslemMedjahdi committed Feb 1, 2023
1 parent adcc429 commit 5cf2143
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 71 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"socket.io-client": "^4.5.4",
"styled-components": "^5.3.6",
"swiper": "^8.4.5",
"tailwind-scrollbar": "^2.1.0",
"tailwindcss": "^3.2.4",
"typescript": "4.9.4"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ type Props = {
};

const ContactForm: React.FC<Props> = ({ AnnouncementId }) => {
const { sendMessage, isConnected } = useMessage();
const { sendMessageByAnnouncementId, isConnected } = useMessage();

const [message, setMessage] = useState<string>("");

const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (isConnected) {
sendMessage(AnnouncementId, message);
sendMessageByAnnouncementId(AnnouncementId, message);
setMessage("");
toast.success("Le message a été envoyé avec succès", {
progressClassName: "!bg-blue-primary",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ const PosterInfo: React.FC<Props> = ({ email, firstName, lastName, phone }) => {
<div className="flex flex-col items-center gap-y-2">
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-blue-hover p-1">
<img
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${
firstName + lastName + email
}`}
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${email}`}
alt="avatar"
className="h-full w-full rounded-full"
/>
Expand Down
17 changes: 15 additions & 2 deletions src/components/layout/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { IMAGES } from "../../../constants/images";
import { INFO } from "../../../constants/info";
import { NAV } from "../../../constants/nav";
import { ROUTES } from "../../../constants/routes";
import useAuth from "../../../hooks/useAuth";
import { useScrollDirection } from "../../../hooks/useScrollDirection";
import ProfileMenu from "./ProfileMenu";

const Header = () => {
const { currentUser } = useAuth();
const router = useRouter();
const scrollDirection = useScrollDirection();

return (
<header className="sticky top-0 z-50 flex justify-center border-b bg-white">
<header
className={`sticky ${
scrollDirection === "down" ? "-top-24" : "top-0"
} z-50 flex justify-center border-b bg-white shadow transition-all duration-500`}
>
<div className="container flex items-center justify-between gap-x-4 py-4 px-4">
<div className="flex items-center gap-x-4">
<Link
Expand All @@ -29,7 +38,11 @@ const Header = () => {
currentUser && allowedRoles.includes(currentUser.role) ? (
<Link
key={index}
className="relative text-base font-semibold after:absolute after:top-full after:left-0 after:h-1 after:w-full after:origin-left after:skew-y-1 after:scale-x-0 after:bg-blue-primary after:transition after:duration-300 hover:after:scale-x-100"
className={`relative text-base font-semibold after:absolute after:top-full after:left-0 after:h-1 after:w-full after:origin-left after:skew-y-1 ${
path === router.pathname
? "after:scale-x-100"
: "after:scale-x-0"
} after:bg-blue-primary after:transition after:duration-300 hover:after:scale-x-100`}
href={path}
>
{name}
Expand Down
4 changes: 1 addition & 3 deletions src/components/layout/header/ProfileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ const ProfileMenu = () => {
const ProfileImage = () => (
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-blue-hover p-1 text-sm font-medium text-white">
<img
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${
currentUser.nom + currentUser.prenom + currentUser.email
}`}
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${currentUser.email}`}
alt="avatar"
className="h-full w-full rounded-full"
/>
Expand Down
72 changes: 58 additions & 14 deletions src/components/messages/DiscussionList.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useMemo, useState } from "react";
import useAuth from "../../hooks/useAuth";
import useMessage from "../../hooks/useMessages";
import DiscussionListItem from "./DiscussionListItem";

Expand All @@ -11,9 +13,27 @@ const DiscussionList: React.FC<Props> = ({
onSelectDiscussion,
}) => {
const { discussions, loading } = useMessage();
const { currentUser } = useAuth();

const [sentDiscussions, recievedDiscussions] = useMemo(() => {
if (!discussions) return [[], []];
const sentDiscussions = discussions.filter(
({ annonceur }) => annonceur.email !== currentUser?.email
);
const recievedDiscussions = discussions.filter(
({ annonceur }) => annonceur.email === currentUser?.email
);
return [sentDiscussions, recievedDiscussions];
}, [discussions, currentUser]);

const [showSentDiscussions, setShowSentDiscussions] = useState(false);

return (
<div className="hidden h-full w-full divide-y overflow-y-auto border bg-white shadow lg:block">
<div
className={`col-span-4 ${
selectedDiscussionId ? "hidden" : ""
} h-full w-full divide-y overflow-y-auto border bg-white shadow md:col-span-1 md:block`}
>
{loading &&
!discussions &&
[1, 2, 3, 4, 5, 6, 7, 8, 9].map((_) => (
Expand All @@ -29,19 +49,43 @@ const DiscussionList: React.FC<Props> = ({
</div>
</div>
))}
{!loading &&
discussions &&
discussions.map(({ annonce, annonceur, demandeur, id, messages }) => (
<DiscussionListItem
key={id}
annonce={annonce}
annonceur={annonceur}
demandeur={demandeur}
lastMessage={messages[messages.length - 1].contenu}
onClick={() => onSelectDiscussion(id)}
selected={selectedDiscussionId === id}
/>
))}
{!loading && discussions && (
<div className="flex h-full flex-col divide-y">
<div className="flex flex-wrap justify-center gap-4 px-2 py-4">
<button
onClick={() => setShowSentDiscussions(false)}
className={`text-white ${
!showSentDiscussions ? "bg-blue-primary" : "bg-gray-400"
} rounded-md px-4 py-1.5 text-sm font-medium shadow-sm transition hover:bg-opacity-95`}
>
Reçues
</button>
<button
onClick={() => setShowSentDiscussions(true)}
className={`text-white ${
showSentDiscussions ? "bg-blue-primary" : "bg-gray-400"
} rounded-md px-4 py-1.5 text-sm font-medium shadow-sm transition hover:bg-opacity-95`}
>
Envoyées
</button>
</div>
<div className="flex-1 overflow-y-auto scrollbar-thin scrollbar-thumb-blue-hover">
{(showSentDiscussions ? sentDiscussions : recievedDiscussions).map(
({ annonce, annonceur, demandeur, id, messages }) => (
<DiscussionListItem
key={id}
annonce={annonce}
annonceur={annonceur}
demandeur={demandeur}
lastMessage={messages[messages.length - 1].contenu}
onClick={() => onSelectDiscussion(id)}
selected={selectedDiscussionId === id}
/>
)
)}
</div>
</div>
)}
</div>
);
};
Expand Down
10 changes: 3 additions & 7 deletions src/components/messages/DiscussionListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const DiscussionListItem: React.FC<Props> = ({
<img
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${
annonceur.email === currentUser?.email
? demandeur.nom + demandeur.prenom + demandeur.email
: annonceur.nom + annonceur.prenom + annonceur.email
? demandeur.email
: annonceur.email
}`}
alt="avatar"
className="h-full w-full rounded-full"
Expand All @@ -46,14 +46,10 @@ const DiscussionListItem: React.FC<Props> = ({
</div>
<div className="flex w-full flex-col gap-y-1">
<p className="w-fit text-sm font-medium text-blue-primary">
<span className="underline">
{annonceur.email === currentUser?.email && "Mon "}
Annonce:
</span>{" "}
{annonce.titre.substring(0, 40)} {annonce.titre.length > 40 && "..."}{" "}
</p>
<p className="text-sm font-medium text-slate-800">
<span className="underline">Avec:</span>{" "}
<span>Avec:</span>{" "}
{annonceur.email === currentUser?.email
? demandeur.nom + " " + demandeur.prenom
: annonceur.nom + " " + annonceur.prenom}
Expand Down
64 changes: 53 additions & 11 deletions src/components/messages/DiscussionMessages.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,68 @@
import React from "react";
import React, { useEffect, useRef } from "react";
import { ICONS } from "../../constants/icons";
import useAuth from "../../hooks/useAuth";
import { Discussions } from "../../typings/discussions";
import { Auth } from "../../typings/user";
import SendMessageForm from "./SendMessageForm";

type Props = {
messages: Discussions.Message[];
announcementId: number;
discussion_id: number;
discussionWith?: Auth.User;
showDiscussionList: () => void;
};

const DiscussionMessages: React.FC<Props> = ({ messages, announcementId }) => {
const DiscussionMessages: React.FC<Props> = ({
messages,
discussion_id,
discussionWith,
showDiscussionList,
}) => {
const { currentUser } = useAuth();

const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
ref.current?.scrollTo(0, ref.current?.scrollHeight);
}, [discussion_id]);

return (
<div className="relative h-full w-full">
<div className="w-full px-2 py-3">
<div className="relative flex h-full w-full flex-col">
<div className="flex items-center gap-x-2 border bg-white px-4 py-3">
<div
role={"button"}
className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-gray-100 transition hover:bg-gray-50 md:hidden"
onClick={showDiscussionList}
>
<ICONS.CHEVRON_LEFT className="text-sm font-medium" />
</div>
<div className="flex h-10 w-10 cursor-pointer items-center justify-center rounded-full bg-blue-hover p-1 text-sm font-medium text-white">
<img
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${
discussionWith?.email || ""
}`}
alt="avatar"
className="h-full w-full rounded-full"
/>
</div>
<p className="text-sm font-semibold">
{discussionWith?.nom} {discussionWith?.prenom}
</p>
</div>
<div
ref={ref}
className="w-full flex-1 overflow-auto px-4 py-3 scrollbar-thin scrollbar-thumb-blue-hover"
>
{messages.map(({ contenu, emetteur, id }) => (
<div key={id} className="flex items-center gap-2">
<div
key={id}
className={`flex ${
currentUser?.email === emetteur.email ? "flex-row-reverse" : ""
} items-center gap-2`}
>
<div className="flex h-10 w-10 cursor-pointer items-center justify-center rounded-full bg-blue-hover p-1 text-sm font-medium text-white">
<img
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${
emetteur.nom + emetteur.prenom + emetteur.email
}`}
src={`https://api.dicebear.com/5.x/bottts/svg?seed=${emetteur.email}`}
alt="avatar"
className="h-full w-full rounded-full"
/>
Expand All @@ -37,8 +79,8 @@ const DiscussionMessages: React.FC<Props> = ({ messages, announcementId }) => {
</div>
))}
</div>
<div className="sticky top-full w-full">
<SendMessageForm announcementId={announcementId} />
<div className="w-full">
<SendMessageForm discussion_id={discussion_id} />
</div>
</div>
);
Expand Down
23 changes: 13 additions & 10 deletions src/components/messages/MessagePreviewIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Image from "next/image";
import { useEffect, useMemo, useRef, useState } from "react";
import { useMemo, useState } from "react";
import { IMAGES } from "../../constants/images";
import useAuth from "../../hooks/useAuth";
import useMessage from "../../hooks/useMessages";
import DiscussionList from "./DiscussionList";
import DiscussionMessages from "./DiscussionMessages";

const MessagePreviewIndex: React.FC = () => {
const { discussions, loading } = useMessage();
const { currentUser } = useAuth();
const [selectedDiscussionId, setSelectedDiscussionId] = useState<
number | undefined
>(undefined);
Expand All @@ -16,12 +18,6 @@ const MessagePreviewIndex: React.FC = () => {
[selectedDiscussionId]
);

const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
ref.current?.scrollTo(0, ref.current?.scrollHeight);
}, [selectedDiscussionId]);

return (
<div className="flex h-full flex-1 justify-center">
<div className="container px-4">
Expand All @@ -36,13 +32,20 @@ const MessagePreviewIndex: React.FC = () => {
onSelectDiscussion={(id) => setSelectedDiscussionId(id)}
/>
<div
ref={ref}
className="relative col-span-4 h-[80vh] w-full overflow-auto bg-white shadow lg:col-span-3"
className={`relative col-span-4 ${
!selectedDiscussionId ? "hidden" : "block"
} h-[80vh] w-full overflow-auto bg-white shadow md:block lg:col-span-3`}
>
{selectedDiscussionId ? (
<DiscussionMessages
discussionWith={
discussion?.annonceur.email === currentUser?.email
? discussion?.demandeur
: discussion?.annonceur
}
messages={discussion?.messages || []}
announcementId={discussion?.id || 0}
discussion_id={discussion?.id || 0}
showDiscussionList={() => setSelectedDiscussionId(undefined)}
/>
) : (
<div className="flex h-full items-center justify-center">
Expand Down
11 changes: 6 additions & 5 deletions src/components/messages/SendMessageForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ import { ICONS } from "../../constants/icons";
import useMessage from "../../hooks/useMessages";

type Props = {
announcementId: number;
discussion_id: number;
};

const SendMessageForm: React.FC<Props> = ({ announcementId }) => {
const { sendMessage } = useMessage();
const SendMessageForm: React.FC<Props> = ({ discussion_id }) => {
const { sendMessageByDiscussionId } = useMessage();

const [message, setMessage] = React.useState<string>("");

const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
sendMessage(announcementId, message);
sendMessageByDiscussionId(discussion_id, message);
setMessage("");
};

return (
Expand All @@ -34,7 +35,7 @@ const SendMessageForm: React.FC<Props> = ({ announcementId }) => {
type="submit"
className="flex items-center gap-2 rounded-xl bg-blue-primary px-4 py-1 text-sm font-medium text-white transition duration-300 hover:bg-blue-hover"
>
<span>Envoyer</span>
<span className="hidden md:flex">Envoyer</span>
<ICONS.SEND />
</button>
</form>
Expand Down
Loading

0 comments on commit 5cf2143

Please sign in to comment.