Ajout des requetes à l'api des channels et de l'affichage dans la page chats. Ajout de la librairie socket.io. Modification legére de l'api.
This commit is contained in:
parent
4ad1da144e
commit
c8541408fd
17 changed files with 296 additions and 734 deletions
11
package.json
11
package.json
|
@ -26,6 +26,7 @@
|
|||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"prisma": "^6.0.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
|
@ -36,14 +37,14 @@
|
|||
"vite": "^5.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"lucide-svelte": "^0.462.0",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"svelte-radix": "^2.0.1"
|
||||
"@prisma/client": "^5.22.0",
|
||||
"@prisma/client": "^6.0.0",
|
||||
"@types/node": "^22.10.1",
|
||||
"argon2": "^0.41.1",
|
||||
"prisma": "^5.22.0",
|
||||
"lucide-svelte": "^0.462.0",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"redis": "^4.7.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"svelte-radix": "^2.0.1",
|
||||
"winston": "^3.17.0"
|
||||
}
|
||||
|
|
116
pnpm-lock.yaml
generated
116
pnpm-lock.yaml
generated
|
@ -8,24 +8,21 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
lucide-svelte:
|
||||
specifier: ^0.462.0
|
||||
version: 0.462.0(svelte@5.2.7)
|
||||
multer:
|
||||
specifier: ^1.4.5-lts.1
|
||||
version: 1.4.5-lts.1
|
||||
'@prisma/client':
|
||||
specifier: ^5.22.0
|
||||
version: 5.22.0(prisma@5.22.0)
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(prisma@6.0.0)
|
||||
'@types/node':
|
||||
specifier: ^22.10.1
|
||||
version: 22.10.1
|
||||
argon2:
|
||||
specifier: ^0.41.1
|
||||
version: 0.41.1
|
||||
prisma:
|
||||
specifier: ^5.22.0
|
||||
version: 5.22.0
|
||||
lucide-svelte:
|
||||
specifier: ^0.462.0
|
||||
version: 0.462.0(svelte@5.2.7)
|
||||
multer:
|
||||
specifier: ^1.4.5-lts.1
|
||||
version: 1.4.5-lts.1
|
||||
redis:
|
||||
specifier: ^4.7.0
|
||||
version: 4.7.0
|
||||
|
@ -78,6 +75,9 @@ importers:
|
|||
prettier-plugin-tailwindcss:
|
||||
specifier: ^0.6.5
|
||||
version: 0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.3.3)(svelte@5.2.7))(prettier@3.3.3)
|
||||
prisma:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
svelte:
|
||||
specifier: ^5.0.0
|
||||
version: 5.2.7
|
||||
|
@ -374,29 +374,29 @@ packages:
|
|||
'@polka/url@1.0.0-next.28':
|
||||
resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
|
||||
|
||||
'@prisma/client@5.22.0':
|
||||
resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==}
|
||||
engines: {node: '>=16.13'}
|
||||
'@prisma/client@6.0.0':
|
||||
resolution: {integrity: sha512-tOBhG35ozqZ/5Y6B0TNOa6cwULUW8ijXqBXcgb12bfozqf6eGMyGs+jphywCsj6uojv5lAZZnxVSoLMVebIP+g==}
|
||||
engines: {node: '>=18.18'}
|
||||
peerDependencies:
|
||||
prisma: '*'
|
||||
peerDependenciesMeta:
|
||||
prisma:
|
||||
optional: true
|
||||
|
||||
'@prisma/debug@5.22.0':
|
||||
resolution: {integrity: sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==}
|
||||
'@prisma/debug@6.0.0':
|
||||
resolution: {integrity: sha512-eUjoNThlDXdyJ1iQ2d7U6aTVwm59EwvODb5zFVNJEokNoSiQmiYWNzZIwZyDmZ+j51j42/0iTaHIJ4/aZPKFRg==}
|
||||
|
||||
'@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2':
|
||||
resolution: {integrity: sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==}
|
||||
'@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e':
|
||||
resolution: {integrity: sha512-JmIds0Q2/vsOmnuTJYxY4LE+sajqjYKhLtdOT6y4imojqv5d/aeVEfbBGC74t8Be1uSp0OP8lxIj2OqoKbLsfQ==}
|
||||
|
||||
'@prisma/engines@5.22.0':
|
||||
resolution: {integrity: sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==}
|
||||
'@prisma/engines@6.0.0':
|
||||
resolution: {integrity: sha512-ZZCVP3q22ifN6Ex6C8RIcTDBlRtMJS2H1ljV0knCiWNGArvvkEbE88W3uDdq/l4+UvyvHpGzdf9ZsCWSQR7ZQQ==}
|
||||
|
||||
'@prisma/fetch-engine@5.22.0':
|
||||
resolution: {integrity: sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==}
|
||||
'@prisma/fetch-engine@6.0.0':
|
||||
resolution: {integrity: sha512-j2m+iO5RDPRI7SUc7sHo8wX7SA4iTkJ+18Sxch8KinQM46YiCQD1iXKN6qU79C1Fliw5Bw/qDyTHaTsa3JMerA==}
|
||||
|
||||
'@prisma/get-platform@5.22.0':
|
||||
resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==}
|
||||
'@prisma/get-platform@6.0.0':
|
||||
resolution: {integrity: sha512-PS6nYyIm9g8C03E4y7LknOfdCw/t2KyEJxntMPQHQZCOUgOpF82Ma60mdlOD08w90I3fjLiZZ0+MadenR3naDQ==}
|
||||
|
||||
'@redis/bloom@1.2.0':
|
||||
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
||||
|
@ -1076,7 +1076,6 @@ packages:
|
|||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
|
||||
is-arrayish@0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
|
||||
|
@ -1107,13 +1106,13 @@ packages:
|
|||
is-reference@3.0.3:
|
||||
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
|
||||
|
||||
|
||||
isarray@1.0.0:
|
||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||
is-stream@2.0.1:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
isarray@1.0.0:
|
||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||
|
||||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
|
@ -1481,9 +1480,9 @@ packages:
|
|||
prism-svelte@0.4.7:
|
||||
resolution: {integrity: sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ==}
|
||||
|
||||
prisma@5.22.0:
|
||||
resolution: {integrity: sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==}
|
||||
engines: {node: '>=16.13'}
|
||||
prisma@6.0.0:
|
||||
resolution: {integrity: sha512-RX7KtbW7IoEByf7MR32JK1PkVYLVYFqeODTtiIX3cqekq1aKdsF3Eud4zp2sUShMLjvdb5Jow0LbUjRq5LVxPw==}
|
||||
engines: {node: '>=18.18'}
|
||||
hasBin: true
|
||||
|
||||
prismjs@1.29.0:
|
||||
|
@ -1505,6 +1504,7 @@ packages:
|
|||
|
||||
readable-stream@2.3.8:
|
||||
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
|
||||
|
||||
readable-stream@3.6.2:
|
||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -1546,6 +1546,7 @@ packages:
|
|||
|
||||
safe-buffer@5.1.2:
|
||||
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
|
@ -1584,11 +1585,12 @@ packages:
|
|||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
stack-trace@0.0.10:
|
||||
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
|
||||
|
||||
streamsearch@1.1.0:
|
||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
stack-trace@0.0.10:
|
||||
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
|
@ -1600,6 +1602,7 @@ packages:
|
|||
|
||||
string_decoder@1.1.1:
|
||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||
|
||||
string_decoder@1.3.0:
|
||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||
|
||||
|
@ -1823,6 +1826,7 @@ packages:
|
|||
xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
|
||||
|
@ -2050,30 +2054,30 @@ snapshots:
|
|||
|
||||
'@polka/url@1.0.0-next.28': {}
|
||||
|
||||
'@prisma/client@5.22.0(prisma@5.22.0)':
|
||||
'@prisma/client@6.0.0(prisma@6.0.0)':
|
||||
optionalDependencies:
|
||||
prisma: 5.22.0
|
||||
prisma: 6.0.0
|
||||
|
||||
'@prisma/debug@5.22.0': {}
|
||||
'@prisma/debug@6.0.0': {}
|
||||
|
||||
'@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': {}
|
||||
'@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e': {}
|
||||
|
||||
'@prisma/engines@5.22.0':
|
||||
'@prisma/engines@6.0.0':
|
||||
dependencies:
|
||||
'@prisma/debug': 5.22.0
|
||||
'@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2
|
||||
'@prisma/fetch-engine': 5.22.0
|
||||
'@prisma/get-platform': 5.22.0
|
||||
'@prisma/debug': 6.0.0
|
||||
'@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e
|
||||
'@prisma/fetch-engine': 6.0.0
|
||||
'@prisma/get-platform': 6.0.0
|
||||
|
||||
'@prisma/fetch-engine@5.22.0':
|
||||
'@prisma/fetch-engine@6.0.0':
|
||||
dependencies:
|
||||
'@prisma/debug': 5.22.0
|
||||
'@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2
|
||||
'@prisma/get-platform': 5.22.0
|
||||
'@prisma/debug': 6.0.0
|
||||
'@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e
|
||||
'@prisma/get-platform': 6.0.0
|
||||
|
||||
'@prisma/get-platform@5.22.0':
|
||||
'@prisma/get-platform@6.0.0':
|
||||
dependencies:
|
||||
'@prisma/debug': 5.22.0
|
||||
'@prisma/debug': 6.0.0
|
||||
|
||||
'@redis/bloom@1.2.0(@redis/client@1.6.0)':
|
||||
dependencies:
|
||||
|
@ -2782,9 +2786,10 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/estree': 1.0.6
|
||||
|
||||
isarray@1.0.0: {}
|
||||
is-stream@2.0.1: {}
|
||||
|
||||
isarray@1.0.0: {}
|
||||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
jackspeak@3.4.3:
|
||||
|
@ -3049,9 +3054,9 @@ snapshots:
|
|||
|
||||
prism-svelte@0.4.7: {}
|
||||
|
||||
prisma@5.22.0:
|
||||
prisma@6.0.0:
|
||||
dependencies:
|
||||
'@prisma/engines': 5.22.0
|
||||
'@prisma/engines': 6.0.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
|
@ -3075,9 +3080,12 @@ snapshots:
|
|||
process-nextick-args: 2.0.1
|
||||
safe-buffer: 5.1.2
|
||||
string_decoder: 1.1.1
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
readable-stream@3.6.2:
|
||||
dependencies:
|
||||
inherits: 2.0.4
|
||||
string_decoder: 1.3.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
readdirp@3.6.0:
|
||||
|
@ -3138,6 +3146,7 @@ snapshots:
|
|||
mri: 1.2.0
|
||||
|
||||
safe-buffer@5.1.2: {}
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
safe-stable-stringify@2.5.0: {}
|
||||
|
@ -3166,9 +3175,10 @@ snapshots:
|
|||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
streamsearch@1.1.0: {}
|
||||
stack-trace@0.0.10: {}
|
||||
|
||||
streamsearch@1.1.0: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
|
@ -3184,6 +3194,7 @@ snapshots:
|
|||
string_decoder@1.1.1:
|
||||
dependencies:
|
||||
safe-buffer: 5.1.2
|
||||
|
||||
string_decoder@1.3.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
@ -3422,6 +3433,7 @@ snapshots:
|
|||
strip-ansi: 7.1.0
|
||||
|
||||
xtend@4.0.2: {}
|
||||
|
||||
yallist@4.0.0: {}
|
||||
|
||||
yaml@1.10.2: {}
|
||||
|
|
|
@ -14,26 +14,22 @@ datasource db {
|
|||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
username String @unique
|
||||
surname String
|
||||
name String
|
||||
email String @unique
|
||||
password String
|
||||
channels Channel[] @relation(fields: [channelIDs], references: [id])
|
||||
channelIDs String[] @db.ObjectId
|
||||
messages Message[]
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
username String @unique
|
||||
surname String
|
||||
name String
|
||||
email String @unique
|
||||
password String
|
||||
messages Message[]
|
||||
|
||||
@@map("users") // Table name in DB
|
||||
}
|
||||
|
||||
model Channel {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
name String
|
||||
topic String
|
||||
users User[] @relation(fields: [userIDs], references: [id])
|
||||
userIDs String[] @db.ObjectId
|
||||
messages Message[]
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
name String @unique
|
||||
messages Message[]
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@map("channels") // Table name in DB
|
||||
}
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
<script lang="ts">
|
||||
export let id: string; // ID du chat
|
||||
export let title: string; // Nom ou titre du chat
|
||||
export let lastMessage: string; // Dernier message affiché
|
||||
export let time: string; // Heure du dernier message
|
||||
</script>
|
||||
|
||||
<div class="chat-item p-4 border rounded-md hover:bg-gray-100 cursor-pointer flex justify-between items-center">
|
||||
<a href={`/chat/${id}`} class="chat-item p-4 border rounded-md hover:bg-gray-100 cursor-pointer flex justify-between items-center">
|
||||
<div>
|
||||
<p class="font-semibold text-lg">{title}</p>
|
||||
<p class="text-sm text-gray-500 truncate">{lastMessage}</p>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400">{time}</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.chat-item {
|
||||
|
|
|
@ -11,12 +11,31 @@
|
|||
|
||||
let chatName = "";
|
||||
|
||||
const createChat = () => {
|
||||
const createChat = async () => {
|
||||
if (chatName.trim()) {
|
||||
alertMessage = `Le chat "${chatName}" a été créé avec succès.`;
|
||||
try {
|
||||
// Appel API pour créer le chat
|
||||
const response = await fetch('/api/canals', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ name: chatName }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
alertMessage = `Le chat "${data.name}" a été créé avec succès.`;
|
||||
chatName = ""; // Réinitialiser
|
||||
onClose?.(); // Fermer le composant après création
|
||||
} else {
|
||||
alertMessage = "Une erreur est survenue lors de la création du chat.";
|
||||
}
|
||||
} catch (err) {
|
||||
alertMessage = "Erreur réseau ou serveur.";
|
||||
}
|
||||
|
||||
showAlert = true;
|
||||
chatName = ""; // Réinitialiser
|
||||
onClose?.(); // Fermer le composant après création
|
||||
} else {
|
||||
alertMessage = "Veuillez entrer un nom pour le chat.";
|
||||
showAlert = true;
|
||||
|
|
51
src/lib/utils/date.ts
Normal file
51
src/lib/utils/date.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
export function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleString('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false, // format 24 heures
|
||||
});
|
||||
}
|
||||
|
||||
//fonction qui renvoie le temps depuis la créetion du message à maintenant en fonction du temps on affichera le temps en secondes, minutes, heures, jours, semaines, mois, années
|
||||
export function formatDistanceToNow(dateString) {
|
||||
const date = new Date(dateString);
|
||||
const now = new Date();
|
||||
const diff = now - date;
|
||||
|
||||
const seconds = Math.floor(diff / 1000);
|
||||
if (seconds < 60) {
|
||||
return `${seconds} s`;
|
||||
}
|
||||
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
if (minutes < 60) {
|
||||
return `${minutes} min`;
|
||||
}
|
||||
|
||||
const hours = Math.floor(minutes / 60);
|
||||
if (hours < 24) {
|
||||
return `${hours} h`;
|
||||
}
|
||||
|
||||
const days = Math.floor(hours / 24);
|
||||
if (days < 7) {
|
||||
return `${days} j`;
|
||||
}
|
||||
|
||||
const weeks = Math.floor(days / 7);
|
||||
if (weeks < 4) {
|
||||
return `${weeks} sem`;
|
||||
}
|
||||
|
||||
const months = Math.floor(days / 30);
|
||||
if (months < 12) {
|
||||
return `${months} mois`;
|
||||
}
|
||||
|
||||
const years = Math.floor(months / 12);
|
||||
return `${years} ans`;
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
import { json } from '@sveltejs/kit';
|
||||
import prisma from '$lib/prismaClient';
|
||||
import redisClient from '$lib/redisClient'; // Assurez-vous d'importer le client Redis
|
||||
|
||||
// Récupérer les informations du canal et le dernier message (avec cache Redis)
|
||||
export async function GET({ params }) {
|
||||
const canalId = parseInt(params.id);
|
||||
|
||||
// Clé cache pour les informations du canal et le dernier message
|
||||
const canalCacheKey = `canal:${canalId}:info`;
|
||||
|
||||
try {
|
||||
// Vérifier si les informations du canal et le dernier message sont dans le cache Redis
|
||||
const cachedCanalData = await redisClient.get(canalCacheKey);
|
||||
if (cachedCanalData) {
|
||||
console.log('✅ Cache hit pour les informations du canal et le dernier message');
|
||||
return json(JSON.parse(cachedCanalData));
|
||||
}
|
||||
|
||||
console.log('❌ Cache miss');
|
||||
// Si non, récupérer les informations du canal et le dernier message depuis Prisma
|
||||
const canal = await prisma.canal.findUnique({
|
||||
where: { id: canalId },
|
||||
include: {
|
||||
users: true, // Inclut les utilisateurs associés au canal
|
||||
},
|
||||
});
|
||||
|
||||
if (!canal) {
|
||||
return json({ error: 'Canal non trouvé' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Récupérer le dernier message
|
||||
const lastMessage = await prisma.message.findFirst({
|
||||
where: { canalId },
|
||||
include: {
|
||||
user: { select: { id: true, pseudo: true } },
|
||||
},
|
||||
orderBy: { createdAt: 'desc' }, // Trie par date décroissante, donc le dernier message est récupéré en premier
|
||||
});
|
||||
|
||||
// Créer un objet combiné pour le canal et le dernier message
|
||||
const canalData = {
|
||||
canal,
|
||||
lastMessage, // Inclure uniquement le dernier message
|
||||
};
|
||||
|
||||
// Mettre en cache les informations du canal et le dernier message pendant 5 minutes
|
||||
await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 300); // Cache pendant 5 minutes
|
||||
|
||||
console.log('❌ Cache miss - Mise en cache des résultats');
|
||||
return json(canalData);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la récupération du canal ou du dernier message' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Supprimer un canal et invalider le cache associé
|
||||
export async function DELETE({ params }) {
|
||||
const canalId = parseInt(params.id);
|
||||
|
||||
try {
|
||||
// Supprimer le canal de la base de données
|
||||
await prisma.canal.delete({
|
||||
where: { id: canalId },
|
||||
});
|
||||
|
||||
// Invalider le cache
|
||||
await redisClient.del(`canal:${canalId}:info`);
|
||||
|
||||
return json({ message: 'Canal supprimé avec succès' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la suppression du canal' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Modifier un canal
|
||||
export async function PUT({ params, request }) {
|
||||
const canalId = parseInt(params.id);
|
||||
const { nom, domaine } = await request.json(); // On suppose que ce sont les champs à mettre à jour
|
||||
|
||||
// Clé cache pour les informations du canal et le dernier message
|
||||
const canalCacheKey = `canal:${canalId}:info`;
|
||||
|
||||
try {
|
||||
// Mettre à jour les informations du canal dans la base de données
|
||||
const updatedCanal = await prisma.canal.update({
|
||||
where: { id: canalId },
|
||||
data: {
|
||||
nom, // Nom du canal
|
||||
domaine, // Domaine du canal
|
||||
},
|
||||
include: {
|
||||
users: true, // Inclut les utilisateurs associés au canal
|
||||
},
|
||||
});
|
||||
|
||||
// Récupérer le dernier message associé au canal après mise à jour
|
||||
const lastMessage = await prisma.message.findFirst({
|
||||
where: { canalId },
|
||||
include: {
|
||||
user: { select: { id: true, pseudo: true } },
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
|
||||
// Créer un objet combiné pour les nouvelles informations du canal et le dernier message
|
||||
const canalData = {
|
||||
canal: updatedCanal,
|
||||
lastMessage, // Inclure uniquement le dernier message
|
||||
};
|
||||
|
||||
// Mettre en cache les nouvelles informations pendant 5 minutes
|
||||
await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 60 * 5); // Cache pendant 5 minutes
|
||||
|
||||
return json(canalData);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la mise à jour du canal' }, { status: 500 });
|
||||
}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
import { json } from '@sveltejs/kit';
|
||||
import prisma from '$lib/prismaClient';
|
||||
import redisClient from '$lib/redisClient'; // Assure-toi d'importer ton client Redis
|
||||
|
||||
export async function GET({ params, url }) {
|
||||
const canalId = parseInt(params.id);
|
||||
|
||||
// Gestion de la pagination avec des paramètres optionnels `page` et `limit`
|
||||
const page = parseInt(url.searchParams.get('page')) || 1;
|
||||
const limit = parseInt(url.searchParams.get('limit')) || 10;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
// Générer une clé cache Redis unique en fonction du canal et des paramètres de pagination
|
||||
const cacheKey = `canal:${canalId}:messages:page:${page}:limit:${limit}`;
|
||||
|
||||
try {
|
||||
// 1. Vérifier si les messages sont déjà dans le cache Redis
|
||||
const cachedMessages = await redisClient.get(cacheKey);
|
||||
if (cachedMessages) {
|
||||
console.log('✅ Cache hit');
|
||||
return json(JSON.parse(cachedMessages)); // Si les données sont en cache, les retourner
|
||||
}
|
||||
|
||||
// 2. Si les messages ne sont pas en cache, récupérer depuis la base de données
|
||||
const messages = await prisma.message.findMany({
|
||||
where: { canalId },
|
||||
include: {
|
||||
user: {
|
||||
select: { id: true, pseudo: true }, // Inclut uniquement l’ID et le pseudo de l’utilisateur
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'asc', // Trie par date croissante
|
||||
},
|
||||
skip: offset,
|
||||
take: limit,
|
||||
});
|
||||
|
||||
// 3. Compter le nombre total de messages pour la pagination
|
||||
const totalMessages = await prisma.message.count({
|
||||
where: { canalId },
|
||||
});
|
||||
|
||||
const response = {
|
||||
messages,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
totalMessages,
|
||||
totalPages: Math.ceil(totalMessages / limit),
|
||||
},
|
||||
};
|
||||
|
||||
// 4. Mettre en cache les messages avec une expiration (par exemple 5 minutes)
|
||||
await redisClient.set(cacheKey, JSON.stringify(response), 'EX', 60 * 5); // Cache pendant 5 minutes
|
||||
|
||||
console.log('❌ Cache miss - Mise en cache des résultats');
|
||||
return json(response); // Retourner les données récupérées
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la récupération des messages' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST({ params, request }) {
|
||||
const canalId = parseInt(params.id);
|
||||
const { userId, text } = await request.json();
|
||||
|
||||
try {
|
||||
// Créer un nouveau message dans la base de données
|
||||
const newMessage = await prisma.message.create({
|
||||
data: {
|
||||
userId,
|
||||
canalId,
|
||||
text,
|
||||
},
|
||||
include: { user: { select: { id: true, pseudo: true } } },
|
||||
});
|
||||
|
||||
updateCaches(); // Mettre à jour les caches après la création d’un nouveau message
|
||||
|
||||
return json(newMessage, { status: 201 });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la création du message' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE({ params }) {
|
||||
const messageId = parseInt(params.id);
|
||||
|
||||
try {
|
||||
// Supprimer le message de la base de données
|
||||
await prisma.message.delete({
|
||||
where: { id: messageId },
|
||||
});
|
||||
|
||||
updateCaches(); // Mettre à jour les caches après la suppression d’un message
|
||||
|
||||
return json({ message: 'Message supprimé avec succès' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la suppression du message' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour mettre à jour tous les caches des messages
|
||||
function updateCaches(canalId) {
|
||||
// Mettre à jour tous les caches
|
||||
// Mettre à jour toutes les pages dans le cache
|
||||
let page : number = 1;
|
||||
let limit : number = 10;
|
||||
let offset : number = (page - 1) * limit;
|
||||
while (true) {
|
||||
const cacheKey = `canal:${canalId}:messages:page:${page}:limit:${limit}`;
|
||||
const cachedMessages = await redisClient.get(cacheKey);
|
||||
if (!cachedMessages) {
|
||||
break;
|
||||
}
|
||||
const totalMessages = await prisma.message.count({
|
||||
where: { canalId },
|
||||
});
|
||||
const messages = await prisma.message.findMany({
|
||||
where: { canalId },
|
||||
include: {
|
||||
user: {
|
||||
select: { id: true, pseudo: true },
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'asc',
|
||||
},
|
||||
skip: offset,
|
||||
take: limit,
|
||||
});
|
||||
const response = {
|
||||
messages,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
totalMessages,
|
||||
totalPages: Math.ceil(totalMessages / limit),
|
||||
},
|
||||
};
|
||||
await redisClient.set(cacheKey, JSON.stringify(response), 'EX', 60 * 5);
|
||||
page++;
|
||||
offset = (page - 1) * limit;
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
import { json } from '@sveltejs/kit';
|
||||
import prisma from '$lib/prismaClient';
|
||||
import redisClient from '$lib/redisClient';
|
||||
|
||||
// GET: Liste tous les canaux
|
||||
export async function GET() {
|
||||
try {
|
||||
const cachedCanaux = await redisClient.get('canaux');
|
||||
if (cachedCanaux) {
|
||||
console.log('✅ Cache hit');
|
||||
return json(JSON.parse(cachedCanaux));
|
||||
}
|
||||
|
||||
console.log('❌ Cache miss');
|
||||
const canaux = await prisma.canal.findMany({
|
||||
include: { users: true, messages: true }, // Inclut les relations
|
||||
});
|
||||
|
||||
await redisClient.set('canaux', JSON.stringify(canaux), { EX: 600 }); // Met en cache
|
||||
return json(canaux);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST({ request }) {
|
||||
const { nom, domaine, userIds } = await request.json();
|
||||
|
||||
try {
|
||||
const canal = await prisma.canal.create({
|
||||
data: {
|
||||
nom,
|
||||
domaine,
|
||||
users: {
|
||||
connect: userIds.map((id) => ({ id })), // Associe des utilisateurs au canal
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return json(canal, { status: 201 });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la création du canal' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
|
@ -2,46 +2,89 @@ import { json } from '@sveltejs/kit';
|
|||
import prisma from '$lib/prismaClient';
|
||||
import redisClient from '$lib/redisClient';
|
||||
|
||||
// GET: Liste tous les canaux
|
||||
import { json } from '@sveltejs/kit';
|
||||
import prisma from '$lib/prismaClient';
|
||||
import redisClient from '$lib/redisClient';
|
||||
|
||||
// GET: Liste tous les canaux avec leur premier message
|
||||
export async function GET() {
|
||||
try {
|
||||
const cachedCanaux = await redisClient.get('canaux');
|
||||
if (cachedCanaux) {
|
||||
console.log('✅ Cache hit');
|
||||
return json(JSON.parse(cachedCanaux));
|
||||
}
|
||||
|
||||
|
||||
|
||||
console.log('❌ Cache miss');
|
||||
const canaux = await prisma.canal.findMany({
|
||||
include: { users: true, messages: true }, // Inclut les relations
|
||||
|
||||
// Si le cache est invalide ou vide, on charge les données depuis la base de données
|
||||
let canaux = await prisma.channel.findMany({
|
||||
include: {
|
||||
messages: {
|
||||
take: 1, // Récupère le dernier message
|
||||
orderBy: { createdAt: 'desc' }, // Trie par date décroissante
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
canaux = canaux.sort((a, b) => {
|
||||
const lastMessageA = a.messages[0]?.createdAt || a.createdAt ? a.createdAt : new Date();
|
||||
const lastMessageB = b.messages[0]?.createdAt || b.createdAt ? b.createdAt : new Date();
|
||||
return new Date(lastMessageB).getTime() - new Date(lastMessageA).getTime();
|
||||
});
|
||||
|
||||
await redisClient.set('canaux', JSON.stringify(canaux), { EX: 600 }); // Met en cache
|
||||
return json(canaux);
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
console.error('Erreur lors de la récupération des canaux:', err);
|
||||
return json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST({ request }) {
|
||||
const { nom, domaine, userIds } = await request.json();
|
||||
console.log('Création d’un canal');
|
||||
const { name } = await request.json(); // Récupère le nom du canal depuis la requête
|
||||
|
||||
try {
|
||||
const canal = await prisma.canal.create({
|
||||
// 1. Créer le canal dans la base de données MongoDB avec Prisma
|
||||
const canal = await prisma.channel.create({
|
||||
data: {
|
||||
nom,
|
||||
domaine,
|
||||
users: {
|
||||
connect: userIds.map((id) => ({ id })), // Associe des utilisateurs au canal
|
||||
},
|
||||
name,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
});
|
||||
console.log('Canal créé dans MongoDB:', canal);
|
||||
|
||||
// 2. Récupérer les canaux existants du cache Redis
|
||||
let canaux = await redisClient.get('canaux');
|
||||
|
||||
// Si le cache est vide, initialiser un tableau vide
|
||||
if (canaux) {
|
||||
try {
|
||||
canaux = JSON.parse(canaux); // Parser la liste existante dans Redis
|
||||
} catch (parseError) {
|
||||
console.error('Erreur lors du parsing du cache Redis:', parseError);
|
||||
canaux = []; // Réinitialiser si parsing échoue
|
||||
}
|
||||
} else {
|
||||
canaux = [];
|
||||
}
|
||||
|
||||
// 3. Ajouter le nouveau canal à la liste des canaux en mémoire (Redis)
|
||||
canaux.push(canal); // Ajoute le canal créé dans la base de données à la liste Redis
|
||||
|
||||
// 4. Mettre à jour le cache Redis avec la liste des canaux
|
||||
await redisClient.set('canaux', JSON.stringify(canaux), { EX: 600 }); // Le cache expire dans 10 minutes
|
||||
console.log('Liste des canaux mise à jour dans Redis');
|
||||
|
||||
// 5. Retourner le canal créé dans la réponse
|
||||
return json(canal, { status: 201 });
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
// Gérer les erreurs et les retourner
|
||||
console.error('Erreur lors de la création du canal:', err);
|
||||
return json({ error: 'Erreur lors de la création du canal' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,200 +0,0 @@
|
|||
import { json } from '@sveltejs/kit';
|
||||
import redisClient from '$lib/redisClient';
|
||||
import prisma from '$lib/prismaClient';
|
||||
import multer from 'multer';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
const destinationDir = '/uploads';
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, `.${destinationDir}'); // Dossier où les images sont stockées`
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, `${Date.now()}-${file.originalname}`);
|
||||
},
|
||||
fileFilter(req, file, cb) {
|
||||
const fileExtension = path.extname(file.originalname).toLowerCase();
|
||||
if (fileExtension !== '.jpg' && fileExtension !== '.jpeg' && fileExtension !== '.png') {
|
||||
return cb(new Error('Seules les images JPG, JPEG et PNG sont autorisées.'));
|
||||
}
|
||||
cb(null, true);
|
||||
}
|
||||
});
|
||||
|
||||
const upload = multer({ storage });
|
||||
|
||||
export async function GET({ params }) {
|
||||
const userId = params.id;
|
||||
|
||||
try {
|
||||
// Vérifier si l'utilisateur est dans le cache Redis
|
||||
const cachedUser = await redisClient.get(`user:${userId}`);
|
||||
if (cachedUser) {
|
||||
console.log('✅ Cache hit');
|
||||
return json(JSON.parse(cachedUser));
|
||||
}
|
||||
|
||||
console.log('❌ Cache miss');
|
||||
// Si non, récupérer depuis MongoDB via Prisma
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: parseInt(userId) },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return json({ error: 'Utilisateur non trouvé' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Mettre l'utilisateur en cache
|
||||
await redisClient.set(`user:${userId}`, JSON.stringify(user), { EX: 3600 });
|
||||
|
||||
return json(user);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour un utilisateur avec PUT
|
||||
export async function PUT({ params, request }) {
|
||||
const userId = parseInt(params.id);
|
||||
|
||||
const cachedUser = await redisClient.get(`user:${userId}`);
|
||||
// Récupérer l'utilisateur à partir de la base de données
|
||||
let existingUser;
|
||||
|
||||
if (cachedUser) {
|
||||
console.log('✅ Cache hit');
|
||||
// Si l'utilisateur est dans le cache, on le parse
|
||||
existingUser = JSON.parse(cachedUser);
|
||||
} else {
|
||||
// Si l'utilisateur n'est pas dans le cache, on le récupère de la base de données
|
||||
console.log('❌ Cache miss');
|
||||
existingUser = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
});
|
||||
|
||||
if (!existingUser) {
|
||||
return json({ error: 'Utilisateur non trouvé' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Utilisation de multer pour récupérer l'image (si présente)
|
||||
return new Promise((resolve, reject) => {
|
||||
upload.single('profilePicture')(request.raw, request.raw, async (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur de téléchargement:', err);
|
||||
return reject(json({ error: 'Erreur lors du téléchargement du fichier' }, { status: 500 }));
|
||||
}
|
||||
|
||||
// Extraire les autres données (pseudo, nom, etc.) du body de la requête
|
||||
const { pseudo, nom, prenom, email, password } = await request.json();
|
||||
|
||||
let updatedUserData = {
|
||||
pseudo,
|
||||
nom,
|
||||
prenom,
|
||||
email,
|
||||
password, // Assurez-vous de bien sécuriser les mots de passe
|
||||
};
|
||||
|
||||
// Si une nouvelle image est envoyée
|
||||
if (request.file) {
|
||||
// Vérifiez si l'utilisateur a déjà une image
|
||||
if (existingUser.profilePictureUrl) {
|
||||
// Supprimer l'ancienne image
|
||||
const oldImagePath = `.${destinationDir}/${path.basename(existingUser.profilePictureUrl)}`;
|
||||
if (fs.existsSync(oldImagePath)) {
|
||||
fs.unlinkSync(oldImagePath); // Suppression du fichier
|
||||
}
|
||||
}
|
||||
|
||||
// Ajouter la nouvelle image à la base de données
|
||||
updatedUserData.profilePictureUrl = `${destinationDir}/${request.file.filename}`;
|
||||
} else if (!request.file && existingUser.profilePictureUrl) {
|
||||
// Si aucune image n'est envoyée, supprimer l'image actuelle
|
||||
const oldImagePath = `.${destinationDir}/${path.basename(existingUser.profilePictureUrl)}`;
|
||||
if (fs.existsSync(oldImagePath)) {
|
||||
fs.unlinkSync(oldImagePath); // Supprimer l'ancienne image
|
||||
}
|
||||
|
||||
// Mettre à jour l'URL de l'image en null
|
||||
updatedUserData.profilePictureUrl = null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Mettre à jour l'utilisateur dans la base de données
|
||||
const updatedUser = await prisma.user.update({
|
||||
where: { id: userId },
|
||||
data: updatedUserData,
|
||||
});
|
||||
|
||||
// Mettre à jour l'utilisateur dans le cache Redis
|
||||
await redisClient.set(`user:${userId}`, JSON.stringify(updatedUser), 'EX', 3600); // Cache pendant 1 heure (3600 secondes)
|
||||
|
||||
// Réponse avec l'utilisateur mis à jour
|
||||
return resolve(json(updatedUser));
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour de l\'utilisateur:', error);
|
||||
return reject(json({ error: 'Erreur lors de la mise à jour de l\'utilisateur' }, { status: 500 }));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export async function DELETE({ params }) {
|
||||
const userId = parseInt(params.id);
|
||||
|
||||
try {
|
||||
// Vérifier si l'utilisateur est dans le cache Redis
|
||||
const cachedUser = await redisClient.get(`user:${userId}`);
|
||||
let userToDelete;
|
||||
|
||||
if (cachedUser) {
|
||||
console.log('✅ Cache hit');
|
||||
// Si l'utilisateur est dans le cache, on le parse
|
||||
userToDelete = JSON.parse(cachedUser);
|
||||
} else {
|
||||
// Si l'utilisateur n'est pas dans le cache, on le récupère de la base de données
|
||||
console.log('❌ Cache miss');
|
||||
userToDelete = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
});
|
||||
|
||||
if (!userToDelete) {
|
||||
return json({ error: 'Utilisateur non trouvé' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Mettre l'utilisateur dans le cache Redis
|
||||
await redisClient.set(`user:${userId}`, JSON.stringify(userToDelete), { EX: 3600 }); // Cache pendant 1 heure
|
||||
}
|
||||
|
||||
// Si l'utilisateur a une image de profil, la supprimer
|
||||
if (userToDelete.profilePictureUrl) {
|
||||
// Calculer le chemin du fichier à supprimer
|
||||
const imagePath = `.${destinationDir}/${path.basename(userToDelete.profilePictureUrl)}`;
|
||||
if (fs.existsSync(imagePath)) {
|
||||
fs.unlinkSync(imagePath); // Supprimer le fichier image
|
||||
}
|
||||
}
|
||||
|
||||
// Supprimer l'utilisateur de la base de données
|
||||
await prisma.user.delete({
|
||||
where: { id: userId },
|
||||
});
|
||||
|
||||
// Supprimer l'utilisateur du cache Redis
|
||||
await redisClient.del(`user:${userId}`);
|
||||
|
||||
// Réponse après suppression réussie
|
||||
return json({ message: 'Utilisateur et image supprimés avec succès' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la suppression de l’utilisateur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -33,43 +33,19 @@ export async function GET({ params }) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function POST({ request }) {
|
||||
const { pseudo, nom, prenom, email, password } = await request.json();
|
||||
|
||||
try {
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
pseudo,
|
||||
nom,
|
||||
prenom,
|
||||
email,
|
||||
password,
|
||||
},
|
||||
});
|
||||
|
||||
// Mettre le nouvel utilisateur dans le cache
|
||||
await redisClient.set(`user:${user.id}`, JSON.stringify(user), { EX: 3600 });
|
||||
|
||||
return json(user, { status: 201 });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la création de l’utilisateur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour un utilisateur avec PUT
|
||||
export async function PUT({ params, request }) {
|
||||
const userId = parseInt(params.id);
|
||||
const { pseudo, nom, prenom, email, password } = await request.json(); // Assurez-vous d'envoyer tous les champs nécessaires dans le body
|
||||
const { username, surname, name, email, password } = await request.json(); // Assurez-vous d'envoyer tous les champs nécessaires dans le body
|
||||
|
||||
try {
|
||||
// Mettre à jour l'utilisateur dans la base de données
|
||||
const updatedUser = await prisma.user.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
pseudo,
|
||||
nom,
|
||||
prenom,
|
||||
username,
|
||||
surname,
|
||||
name,
|
||||
email,
|
||||
password, // Attention à ne pas oublier de sécuriser le mot de passe avec bcrypt ou une autre méthode
|
||||
},
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
// src/routes/api/users/+server.js
|
||||
import { json } from '@sveltejs/kit';
|
||||
import redisClient from '$lib/redisClient';
|
||||
import prisma from '$lib/prismaClient';
|
||||
import multer from 'multer';
|
||||
|
||||
const destinationDir = '/uploads';
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, `.${destinationDir}'); // Dossier où les images sont stockées`
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, `${Date.now()}-${file.originalname}`);
|
||||
},
|
||||
fileFilter(req, file, cb) {
|
||||
const fileExtension = path.extname(file.originalname).toLowerCase();
|
||||
if (fileExtension !== '.jpg' && fileExtension !== '.jpeg' && fileExtension !== '.png') {
|
||||
return cb(new Error('Seules les images JPG, JPEG et PNG sont autorisées.'));
|
||||
}
|
||||
cb(null, true);
|
||||
}
|
||||
});
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Vérifier si les utilisateurs sont dans le cache Redis
|
||||
const cachedUsers = await redisClient.get('users');
|
||||
if (cachedUsers) {
|
||||
console.log('✅ Cache hit');
|
||||
return json(JSON.parse(cachedUsers));
|
||||
}
|
||||
|
||||
console.log('❌ Cache miss');
|
||||
// Sinon, récupérer les utilisateurs depuis MongoDB
|
||||
const users = await prisma.user.findMany();
|
||||
|
||||
// Mettre les utilisateurs en cache
|
||||
await redisClient.set('users', JSON.stringify(users), { EX: 600 });
|
||||
|
||||
return json(users);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST({ request }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Utilisation de multer pour récupérer le fichier
|
||||
upload.single('profilePicture')(request.raw, request.raw, async (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur de téléchargement:', err);
|
||||
return reject(json({ error: 'Erreur lors du téléchargement du fichier' }, { status: 500 }));
|
||||
}
|
||||
|
||||
// Récupérer les données du formulaire (sans le fichier)
|
||||
const { pseudo, nom, prenom, email, password } = await request.json();
|
||||
|
||||
// L'URL de l'image sera le chemin relatif à partir du dossier uploads
|
||||
const imageUrl = request.file ? `${destinationDir}/${request.file.filename}` : null;
|
||||
|
||||
try {
|
||||
// Créer un nouvel utilisateur avec l'URL de l'image
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
pseudo,
|
||||
nom,
|
||||
prenom,
|
||||
email,
|
||||
password,
|
||||
profilePictureUrl: imageUrl, // Stocker l'URL de l'image
|
||||
},
|
||||
});
|
||||
|
||||
// Mettre l'utilisateur dans le cache Redis
|
||||
await redisClient.set(`user:${user.id}`, JSON.stringify(user), { EX: 3600 });
|
||||
|
||||
// Réponse avec les données de l'utilisateur
|
||||
return resolve(json(user, { status: 201 }));
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la création de l\'utilisateur:', error);
|
||||
return reject(json({ error: 'Erreur lors de la création de l\'utilisateur' }, { status: 500 }));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -25,3 +25,27 @@ export async function GET() {
|
|||
return json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST({ request }) {
|
||||
const { username, surname, name, email, password } = await request.json();
|
||||
|
||||
try {
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
surname,
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
},
|
||||
});
|
||||
|
||||
// Mettre le nouvel utilisateur dans le cache
|
||||
await redisClient.set(`user:${user.id}`, JSON.stringify(user), { EX: 3600 });
|
||||
|
||||
return json(user, { status: 201 });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return json({ error: 'Erreur lors de la création de l’utilisateur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
import ChatItem from "$lib/components/ui/ChatItem.svelte";
|
||||
import ProfileCard from "$lib/components/ui/ProfileCard.svelte"; // Importer le composant ProfileCard
|
||||
import CreateChat from "$lib/components/ui/CreateChat.svelte"; // Importer le composant CreateChat
|
||||
import { formatDistanceToNow } from "$lib/utils/date.js";
|
||||
import { io } from 'socket.io-client';
|
||||
|
||||
let showProfileCard = false; // État pour afficher ou masquer le ProfileCard
|
||||
let showCreateChat = false; // État pour afficher ou masquer CreateChat
|
||||
|
@ -35,6 +37,11 @@
|
|||
console.log('closeCreateChat');
|
||||
showCreateChat = false; // Fermer le composant CreateChat
|
||||
}
|
||||
|
||||
export let data;
|
||||
export let channels = data.channels;// Assurez-vous que 'lastMessage' est facultatif si nécessaire
|
||||
console.log(channels);
|
||||
|
||||
</script>
|
||||
|
||||
<div class="h-full flex flex-col gap-5 p-5">
|
||||
|
@ -67,8 +74,9 @@
|
|||
</div>
|
||||
|
||||
<div class="flex flex-col gap-4 overflow-y-auto">
|
||||
<ChatItem title="Discussion avec Yanax" lastMessage="Salut les amis !" time="12:34" />
|
||||
<ChatItem title="Discussion avec Luxray" lastMessage="Salut Yanax" time="12:30" />
|
||||
{#each channels as channel}
|
||||
<ChatItem id={channel.id} title={channel.name} lastMessage={channel.lastMessage} time={formatDistanceToNow(channel.createdAt)} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
22
src/routes/chats/+page.ts
Normal file
22
src/routes/chats/+page.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
export async function load({ fetch }) {
|
||||
try {
|
||||
// Appel API ou récupération de données
|
||||
const res = await fetch('/api/canals', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
const channels = await res.json();
|
||||
|
||||
// Retourner les données à la page sous forme de props
|
||||
return {
|
||||
channels
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des canaux:', error);
|
||||
return {
|
||||
channels: []
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,6 +1,21 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { type ViteDevServer, defineConfig } from 'vite';
|
||||
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
const webSocketServer = {
|
||||
name: 'webSocketServer',
|
||||
configureServer(server: ViteDevServer) {
|
||||
if (!server.httpServer) return
|
||||
|
||||
const io = new Server(server.httpServer)
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
socket.emit('eventFromServer', 'Hello, World 👋')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()]
|
||||
plugins: [sveltekit(), webSocketServer]
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue