Modification de la page de chat et des requetes de création de channel

This commit is contained in:
Bilal Dieumegard 2024-12-02 19:53:40 +01:00
parent cbf953a25b
commit 45eba3eb1d
6 changed files with 180 additions and 45 deletions

View file

@ -1,15 +1,47 @@
<script lang="ts">
import * as Card from "$lib/components/ui/card";
import { formatDistanceToNow } from "$lib/utils/date.js";
export let username;
export let messageContent;
export let username: string;
export let messageContent: string;
export let profilePicture: string | null; // Peut être null
export let createdAt: string; // Date de création du message
// Image par défaut si profilePicture est null
let defaultProfilePicture = "/images/default-profile.png";
</script>
<Card.Root>
<Card.Header>
<Card.Title>{username}</Card.Title>
<Card.Root class="relative">
<Card.Header class="flex items-center flex-row justify-between">
<!-- Image de profil collée à gauche -->
<div class="flex flex-row gap-3 items-center">
<img
src={profilePicture || defaultProfilePicture}
alt="Profile Picture"
class="h-10 w-10 rounded-full border border-gray-300"
/>
<!-- Section contenant le pseudo -->
<div class="flex flex-col">
<Card.Title class="text-gray-800 text-sm sm:text-base md:text-lg truncate">
{username}
</Card.Title>
</div>
</div>
<span class="text-xs sm:text-sm md:text-base text-gray-500 items-top">
{formatDistanceToNow(createdAt)}
</span>
</Card.Header>
<!-- Contenu du message -->
<Card.Content>
<p class="text-sm sm:text-base md:text-lg text-gray-700">
{messageContent}
</p>
</Card.Content>
</Card.Root>
<style>
img {
object-fit: cover; /* Assure un bon rendu des images */
}
</style>

View file

@ -0,0 +1,58 @@
<script lang="ts">
export let profilePicture: string; // URL de l'image de profil
export let username: string; // Pseudo de l'utilisateur
export let status: string = "En ligne"; // Statut par défaut
</script>
<div class="flex items-center gap-4 p-3 cursor-pointer hover:bg-gray-100 rounded-lg border border-gray-300 shadow-sm">
<img
src={profilePicture}
alt="Profile"
class="h-12 w-12 rounded-full border border-gray-300"
/>
<div class="flex flex-col">
<span class="font-medium text-gray-800">{username}</span>
<div class="flex items-center gap-1">
<span class="text-xs text-gray-500">{status}</span>
{#if status === "En ligne"}
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-3 w-3 text-green-500"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
</svg>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-3 w-3 text-gray-500"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
</svg>
{/if}
</div>
</div>
</div>
<style>
/* Ajout d'une animation subtile lors du survol */
div:hover {
background-color: #f3f4f6;
transition: background-color 0.2s ease-in-out;
}
</style>

View file

@ -23,12 +23,7 @@ export async function GET({ params, url }) {
},
});
canaux = canaux.sort((a, b) => {
const lastMessageA = a.messages[0]?.createdAt || a.createdAt;
const lastMessageB = b.messages[0]?.createdAt || b.createdAt;
return new Date(lastMessageB).getTime() - new Date(lastMessageA).getTime();
});
canaux = sortChannels(canaux);
return json(canaux);
@ -55,12 +50,7 @@ export async function GET({ params, url }) {
},
});
canaux = canaux.sort((a, b) => {
const lastMessageA = a.messages[0]?.createdAt || a.createdAt;
const lastMessageB = b.messages[0]?.createdAt || b.createdAt;
return new Date(lastMessageB).getTime() - new Date(lastMessageA).getTime();
});
canaux = sortChannels(canaux);
logger.debug('Caching channels with EX of 3600 secs');
await redisClient.set('channels', JSON.stringify(canaux), { EX: 3600 });
@ -81,28 +71,40 @@ export async function POST({ request }) {
try {
const canal = await prisma.channel.create({
data: {
name,
createdAt: new Date(),
name
},
});
logger.debug('Creating a new channel in database with id ' + canal.id);
const cachedChanels = await redisClient.get('channels');
const channels = cachedChanels != null ? JSON.parse(cachedChanels) : [];
let channels = cachedChanels != null ? JSON.parse(cachedChanels) : [];
console.log(channels);
console.log(canal);
channels.push(canal);
channels = sortChannels(channels);
console.log(channels);
logger.debug(`Added channel (${canal.id}) to channels cache.`);
await redisClient.set('channels', JSON.stringify(channels), { EX: 600 });
return json(canal, { status: 201 });
} catch (err) {
console.log(err);
logger.error(err);
return json({ error: 'Erreur lors de la création du canal' }, { status: 500 });
}
}
function sortChannels(channels) {
return channels.sort((a, b) => {
// Vérifie si 'a.messages' existe et est un tableau, sinon utilise la date de création du canal
const lastMessageA = Array.isArray(a.messages) && a.messages.length > 0 ? a.messages[0]?.createdAt : a.createdAt;
const lastMessageB = Array.isArray(b.messages) && b.messages.length > 0 ? b.messages[0]?.createdAt : b.createdAt;
return new Date(lastMessageB).getTime() - new Date(lastMessageA).getTime();
});
}

View file

@ -104,21 +104,21 @@ export async function DELETE({ params }) {
}
// Fonction pour mettre à jour tous les caches des messages
function updateCaches(channelId: string) {
async function updateCaches(channelId: string) {
let page : number = 1;
let limit : number = 10;
let offset : number = (page - 1) * limit;
while (true) {
const cacheKey = `channel:${channelId}:messages:page:${page}:limit:${limit}`;
const cacheKey = `channel:${channelId}:messages:page:${page}`;
const cachedMessages = await redisClient.get(cacheKey);
if (!cachedMessages) {
break;
}
const totalMessages = await prisma.message.count({
where: { canalId },
where: { channelId },
});
const messages = await prisma.message.findMany({
where: { canalId },
where: { channelId },
include: {
user: {
select: { id: true, pseudo: true },

View file

@ -5,7 +5,7 @@ export async function load({ fetch, params }) {
headers: {
'Content-Type': 'application/json'
}
}
});
const messages = await res.json();
return {
messages

View file

@ -3,21 +3,64 @@
import { Button } from "$lib/components/ui/button";
import PaperPlane from "svelte-radix/PaperPlane.svelte";
import Message from "$lib/components/Message.svelte";
import UserChat from '$lib/components/ui/UserChat.svelte';
export let data;
export let messages = data.messages;
export let users = data.users; // Liste des utilisateurs
let selectedUser = null; // Utilisateur actuellement sélectionné
</script>
<div class="h-full">
<div class="px-10 flex flex-col gap-5 h-[90%]">
<Message username="Yanax" messageContent="Salut les amis" />
<Message username="Luxray" messageContent="Salut Yanax" />
<div class="h-full flex">
<!-- Liste des utilisateurs (colonne gauche) -->
<div class="w-1/4 bg-gray-100 border-r overflow-y-auto">
<h2 class="text-3xl font-bold px-4 mt-5">Utilisateurs</h2>
<div class="flex flex-col m-5 gap-2">
<UserChat
profilePicture="/images/default-profile.png"
username="Luxray555"
status="En ligne"
/>
{#each users as user}
<UserChat
profilePicture={user.profilePicture}
username={user.username}
status={user.status}
/>
{/each}
</div>
<div class="fixed bottom-5 px-10 w-full flex gap-2">
<Textarea class="h-20 resize-none" placeholder="Messsage..." />
<Button size="icon" class="h-20 w-20">
<PaperPlane class="h-18 w-18" />
</div>
<!-- Chat principal (colonne droite) -->
<div class="flex-1 flex flex-col h-full">
<!-- Messages -->
<div class="m-10 flex flex-col gap-5 overflow-y-auto flex-grow ">
<!-- Afficher les messages (mock d'un utilisateur sélectionné ou aucun message par défaut) -->
<Message username="Luxray555" messageContent="Sélectionnez un message pour commencer à discuter." />
{#if messages.length > 0}
{#each messages as message}
<Message username={message.username} messageContent={message.messageContent} />
{/each}
{:else}
<div class="text-center text-gray-500 mt-10">Sélectionnez un message le chat est vide.</div>
{/if}
</div>
<!-- Input pour envoyer un message -->
<div class="px-10 py-5 w-full flex gap-2 border-t">
<Textarea class="h-16 resize-none flex-grow" placeholder="Écrivez un message..." />
<Button size="icon" class="h-16 w-16 bg-blue-500 hover:bg-blue-600 h-full">
<PaperPlane class="h-6 w-6" />
</Button>
</div>
</div>
</div>
<style>
.h-full {
height: 100%;
}
.selected {
background-color: #e2e8f0;
}
</style>