From 2f2fc18f75af6bdd2a00f7ad9a548174f4239714 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 16:34:50 +0900 Subject: [PATCH 01/20] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=EC=A7=80=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/type/session.d.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frontend/src/hooks/type/session.d.ts b/frontend/src/hooks/type/session.d.ts index 200d7fbf..a013259a 100644 --- a/frontend/src/hooks/type/session.d.ts +++ b/frontend/src/hooks/type/session.d.ts @@ -9,6 +9,9 @@ export interface RoomMetadata { inProgress: boolean; host: UserInfo; category: string | string[]; + questionListId: number; + questionListContents: Question[]; + currentIndex: number; } export interface RoomJoinResponse { @@ -22,6 +25,16 @@ export interface RoomJoinResponse { title: string; id: string; connectionMap: { [socketId: string]: UserInfo }; + questionListId: number; + questionListContents: Question[]; + currentIndex: number; +} + +export interface Question { + id: number; + content: string; + index: number; + questionListId: number; } export interface UserInfo { From 48814da38a566409cc5f93c027aa69318d166e51 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 16:35:04 +0900 Subject: [PATCH 02/20] chore: pnpm-lock --- pnpm-lock.yaml | 373 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd77782f..b9f71188 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,12 @@ importers: mysql2: specifier: ^3.11.4 version: 3.11.4 + nestjs-paginate: + specifier: ^10.0.0 + version: 10.0.0(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/swagger@8.0.7(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2))(express@4.21.1)(fastify@4.28.1)(typeorm@0.3.20(ioredis@5.4.1)(mysql2@3.11.4)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.4)(typescript@5.6.3))) + nestjs-redis-om: + specifier: ^0.1.2 + version: 0.1.2(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(redis-om@0.4.7)(reflect-metadata@0.2.2) passport: specifier: ^0.7.0 version: 0.7.0 @@ -786,6 +792,18 @@ packages: resolution: {integrity: sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fastify/ajv-compiler@3.6.0': + resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} + + '@fastify/error@3.4.1': + resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + + '@fastify/fast-json-stringify-compiler@4.3.0': + resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} + + '@fastify/merge-json-schemas@0.1.1': + resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1041,6 +1059,9 @@ packages: resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} engines: {node: '>=8'} + '@microsoft/tsdoc@0.15.1': + resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} + '@moozeh/nestjs-redis-om@0.1.4': resolution: {integrity: sha512-p0UT1WccsLNKOpa5E69fknJZFZAbK2LOImK4JWuuXtGnFJ2DSGtZ8Jbm4TNV6VkdL6x5yqg8YeX44DdZQHuZfA==} peerDependencies: @@ -1097,6 +1118,19 @@ packages: peerDependencies: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/mapped-types@2.0.6': + resolution: {integrity: sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + class-transformer: ^0.4.0 || ^0.5.0 + class-validator: ^0.13.0 || ^0.14.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + '@nestjs/passport@10.0.3': resolution: {integrity: sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==} peerDependencies: @@ -1121,6 +1155,23 @@ packages: peerDependencies: typescript: '>=4.8.2' + '@nestjs/swagger@8.0.7': + resolution: {integrity: sha512-zaTMCEZ/CxX7QYF110nTqJsn7eCXp4VI9kv7+AdUcIlBmhhgJpggBw2Mx2p6xVjyz1EoWXGfxxWKnxEyaQwFlg==} + peerDependencies: + '@fastify/static': ^6.0.0 || ^7.0.0 + '@nestjs/common': ^9.0.0 || ^10.0.0 + '@nestjs/core': ^9.0.0 || ^10.0.0 + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 || ^0.2.0 + peerDependenciesMeta: + '@fastify/static': + optional: true + class-transformer: + optional: true + class-validator: + optional: true + '@nestjs/testing@10.4.6': resolution: {integrity: sha512-aiDicKhlGibVGNYuew399H5qZZXaseOBT/BS+ERJxxCmco7ZdAqaujsNjSaSbTK9ojDPf27crLT0C4opjqJe3A==} peerDependencies: @@ -1318,6 +1369,9 @@ packages: cpu: [x64] os: [win32] + '@scarf/scarf@1.4.0': + resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -1692,6 +1746,9 @@ packages: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} deprecated: Use your platform's native atob() and btoa() methods instead + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -1730,6 +1787,14 @@ packages: ajv: optional: true + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-keywords@3.5.2: resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -1827,6 +1892,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + autoprefixer@10.4.20: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -1834,6 +1903,9 @@ packages: peerDependencies: postcss: ^8.1.0 + avvio@8.4.0: + resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} + aws-ssl-profiles@1.1.2: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} @@ -2562,6 +2634,12 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + fast-content-type-parse@1.1.0: + resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} + + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2575,15 +2653,31 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fast-json-stringify@5.16.1: + resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} + fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} + fast-uri@3.0.3: resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + fastify@4.28.1: + resolution: {integrity: sha512-kFWUtpNr4i7t5vY2EJPCN2KgMVpuqfU4NjnJNCgiNB900oiDeYqaNDRcAfeBbOF5hGixixxcKnOU4KN9z6QncQ==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -2616,6 +2710,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + find-my-way@8.2.2: + resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} + engines: {node: '>=14'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -3190,6 +3288,9 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-ref-resolver@1.0.1: + resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -3253,6 +3354,9 @@ packages: libphonenumber-js@1.11.14: resolution: {integrity: sha512-sexvAfwcW1Lqws4zFp8heAtAEXbEDnvkYCEGzvOoMgZR7JhXo/IkE9MkkGACgBed5fWqh3ShBGnJBdDnU9N8EQ==} + light-my-request@5.14.0: + resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3509,6 +3613,23 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + nestjs-paginate@10.0.0: + resolution: {integrity: sha512-2nv6JC0tDZ9bPH+4bDRIdF4coQS5iE9J5yO9Z047buxSPv0uSd4XzEBtd2h/Nslj342jhoQrQUg0XpyY0KQ7TA==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/swagger': ^8.0.7 + express: ^4.0.0 + fastify: ^4.0.0 + typeorm: ^0.3.17 + + nestjs-redis-om@0.1.2: + resolution: {integrity: sha512-QTY0EkpIB+Fdm0KXs7fzpgLbF0NJumEcyZ1dA4Fi0/FlPEc4QirFP6Qj9QdkxIIzdg2yi+MB6LIZ3pflSiUEMA==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 + redis-om: ^0.4.3 + reflect-metadata: ^0.1.13 || ^0.2.0 + node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} @@ -3560,6 +3681,10 @@ packages: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -3708,6 +3833,16 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.5.0: + resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==} + hasBin: true + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -3785,6 +3920,12 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process-warning@3.0.0: + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} + + process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -3819,6 +3960,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} @@ -3895,6 +4039,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -3962,10 +4110,17 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} + ret@0.4.3: + resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + engines: {node: '>=10'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -3996,6 +4151,13 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex2@3.1.0: + resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -4010,6 +4172,9 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -4037,6 +4202,9 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -4109,6 +4277,9 @@ packages: resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} engines: {node: '>=10.2.0'} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -4243,6 +4414,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + swagger-ui-dist@5.18.2: + resolution: {integrity: sha512-J+y4mCw/zXh1FOj5wGJvnAajq6XgHOyywsa9yITmwxIlJbMqITq3gYRZHaeqLVH/eV/HOPphE6NjF+nbSNC5Zw==} + symbol-observable@4.0.0: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} engines: {node: '>=0.10'} @@ -4302,6 +4476,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -4319,6 +4496,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -5337,6 +5518,22 @@ snapshots: dependencies: levn: 0.4.1 + '@fastify/ajv-compiler@3.6.0': + dependencies: + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + fast-uri: 2.4.0 + + '@fastify/error@3.4.1': {} + + '@fastify/fast-json-stringify-compiler@4.3.0': + dependencies: + fast-json-stringify: 5.16.1 + + '@fastify/merge-json-schemas@0.1.1': + dependencies: + fast-deep-equal: 3.1.3 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -5657,6 +5854,8 @@ snapshots: '@lukeed/csprng@1.1.0': {} + '@microsoft/tsdoc@0.15.1': {} + '@moozeh/nestjs-redis-om@0.1.4(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(redis-om@0.4.7)(reflect-metadata@0.2.2)': dependencies: '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) @@ -5725,6 +5924,14 @@ snapshots: '@types/jsonwebtoken': 9.0.5 jsonwebtoken: 9.0.2 + '@nestjs/mapped-types@2.0.6(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)': + dependencies: + '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + reflect-metadata: 0.2.2 + optionalDependencies: + class-transformer: 0.5.1 + class-validator: 0.14.1 + '@nestjs/passport@10.0.3(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(passport@0.7.0)': dependencies: '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) @@ -5776,6 +5983,21 @@ snapshots: transitivePeerDependencies: - chokidar + '@nestjs/swagger@8.0.7(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)': + dependencies: + '@microsoft/tsdoc': 0.15.1 + '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.4.6(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.6)(@nestjs/websockets@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/mapped-types': 2.0.6(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2) + js-yaml: 4.1.0 + lodash: 4.17.21 + path-to-regexp: 3.3.0 + reflect-metadata: 0.2.2 + swagger-ui-dist: 5.18.2 + optionalDependencies: + class-transformer: 0.5.1 + class-validator: 0.14.1 + '@nestjs/testing@10.4.6(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(@nestjs/platform-express@10.4.6)': dependencies: '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) @@ -5930,6 +6152,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.24.3': optional: true + '@scarf/scarf@1.4.0': {} + '@sinclair/typebox@0.27.8': {} '@sinonjs/commons@3.0.1': @@ -6462,6 +6686,8 @@ snapshots: abab@2.0.6: {} + abstract-logging@2.0.1: {} + accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -6496,6 +6722,14 @@ snapshots: optionalDependencies: ajv: 8.12.0 + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv-keywords@3.5.2(ajv@6.12.6): dependencies: ajv: 6.12.6 @@ -6582,6 +6816,8 @@ snapshots: asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} + autoprefixer@10.4.20(postcss@8.4.47): dependencies: browserslist: 4.24.2 @@ -6592,6 +6828,11 @@ snapshots: postcss: 8.4.47 postcss-value-parser: 4.2.0 + avvio@8.4.0: + dependencies: + '@fastify/error': 3.4.1 + fastq: 1.17.1 + aws-ssl-profiles@1.1.2: {} axios@1.7.7: @@ -7445,6 +7686,10 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-content-type-parse@1.1.0: {} + + fast-decode-uri-component@1.0.1: {} + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -7459,12 +7704,49 @@ snapshots: fast-json-stable-stringify@2.1.0: {} + fast-json-stringify@5.16.1: + dependencies: + '@fastify/merge-json-schemas': 0.1.1 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-deep-equal: 3.1.3 + fast-uri: 2.4.0 + json-schema-ref-resolver: 1.0.1 + rfdc: 1.4.1 + fast-levenshtein@2.0.6: {} + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-redact@3.5.0: {} + fast-safe-stringify@2.1.1: {} + fast-uri@2.4.0: {} + fast-uri@3.0.3: {} + fastify@4.28.1: + dependencies: + '@fastify/ajv-compiler': 3.6.0 + '@fastify/error': 3.4.1 + '@fastify/fast-json-stringify-compiler': 4.3.0 + abstract-logging: 2.0.1 + avvio: 8.4.0 + fast-content-type-parse: 1.1.0 + fast-json-stringify: 5.16.1 + find-my-way: 8.2.2 + light-my-request: 5.14.0 + pino: 9.5.0 + process-warning: 3.0.0 + proxy-addr: 2.0.7 + rfdc: 1.4.1 + secure-json-parse: 2.7.0 + semver: 7.6.3 + toad-cache: 3.7.0 + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -7507,6 +7789,12 @@ snapshots: transitivePeerDependencies: - supports-color + find-my-way@8.2.2: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 3.1.0 + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -8310,6 +8598,10 @@ snapshots: json-parse-even-better-errors@2.3.1: {} + json-schema-ref-resolver@1.0.1: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -8377,6 +8669,12 @@ snapshots: libphonenumber-js@1.11.14: {} + light-my-request@5.14.0: + dependencies: + cookie: 0.7.2 + process-warning: 3.0.0 + set-cookie-parser: 2.7.1 + lilconfig@2.1.0: {} lilconfig@3.1.2: {} @@ -8579,6 +8877,23 @@ snapshots: neo-async@2.6.2: {} + nestjs-paginate@10.0.0(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/swagger@8.0.7(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2))(express@4.21.1)(fastify@4.28.1)(typeorm@0.3.20(ioredis@5.4.1)(mysql2@3.11.4)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.4)(typescript@5.6.3))): + dependencies: + '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/swagger': 8.0.7(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2) + express: 4.21.1 + fastify: 4.28.1 + lodash: 4.17.21 + typeorm: 0.3.20(ioredis@5.4.1)(mysql2@3.11.4)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.4)(typescript@5.6.3)) + + nestjs-redis-om@0.1.2(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.6)(redis-om@0.4.7)(reflect-metadata@0.2.2): + dependencies: + '@nestjs/common': 10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.4.6(@nestjs/common@10.4.6(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.6)(@nestjs/websockets@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1) + redis-om: 0.4.7 + reflect-metadata: 0.2.2 + uuid: 9.0.1 + node-abort-controller@3.1.1: {} node-emoji@1.11.0: @@ -8611,6 +8926,8 @@ snapshots: object-inspect@1.13.2: {} + on-exit-leak-free@2.1.2: {} + on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -8749,6 +9066,26 @@ snapshots: pify@2.3.0: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.0.0: {} + + pino@9.5.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.6: {} pkg-dir@4.2.0: @@ -8817,6 +9154,10 @@ snapshots: process-nextick-args@2.0.1: {} + process-warning@3.0.0: {} + + process-warning@4.0.0: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -8851,6 +9192,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 @@ -8934,6 +9277,8 @@ snapshots: dependencies: picomatch: 2.3.1 + real-require@0.2.0: {} + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -8996,8 +9341,12 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + ret@0.4.3: {} + reusify@1.0.4: {} + rfdc@1.4.1: {} + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -9042,6 +9391,12 @@ snapshots: safe-buffer@5.2.1: {} + safe-regex2@3.1.0: + dependencies: + ret: 0.4.3 + + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} saxes@6.0.0: @@ -9058,6 +9413,8 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) + secure-json-parse@2.7.0: {} + semver@5.7.2: {} semver@6.3.1: {} @@ -9097,6 +9454,8 @@ snapshots: transitivePeerDependencies: - supports-color + set-cookie-parser@2.7.1: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -9225,6 +9584,10 @@ snapshots: - supports-color - utf-8-validate + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + source-map-js@1.2.1: {} source-map-support@0.5.13: @@ -9364,6 +9727,10 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + swagger-ui-dist@5.18.2: + dependencies: + '@scarf/scarf': 1.4.0 + symbol-observable@4.0.0: {} symbol-tree@3.2.4: {} @@ -9436,6 +9803,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + through@2.3.8: {} tinyexec@0.3.1: {} @@ -9450,6 +9821,8 @@ snapshots: dependencies: is-number: 7.0.0 + toad-cache@3.7.0: {} + toidentifier@1.0.1: {} tough-cookie@4.1.4: From eb9f7c4a4ce67df9d3e1925a5fa280ab9f5e6d13 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 16:35:27 +0900 Subject: [PATCH 03/20] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EC=9B=B9=EC=86=8C=EC=BC=93=20API=20=EC=9D=B4=EB=B2=A4=ED=8A=B8?= =?UTF-8?q?=EB=AA=85=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/WebSocket/StudyEvent.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 frontend/src/constants/WebSocket/StudyEvent.ts diff --git a/frontend/src/constants/WebSocket/StudyEvent.ts b/frontend/src/constants/WebSocket/StudyEvent.ts new file mode 100644 index 00000000..1d7b130b --- /dev/null +++ b/frontend/src/constants/WebSocket/StudyEvent.ts @@ -0,0 +1,16 @@ +export const STUDY_EMIT_EVENT = { + NEXT: "client:study__next_question", + CURRENT: "client:study__current_index", + INDEX: "client:study__move_index", + START: "client:study__start_progress", + STOP: "client:study__stop_progress", +}; + +export const STUDY_LISTEN_EVENT = { + NEXT: "server:study__next_question", + CURRENT: "server:study__current_index", + INDEX: "server:study__move_index", + START: "server:study__start_progress", + STOP: "server:study__stop_progress", + PROGRESS: "server:room__progress", +}; From 687c092927adbd7202a12396fe5eaee87c49c989 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 16:35:56 +0900 Subject: [PATCH 04/20] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94?= =?UTF-8?q?=EA=B0=80=20=EC=A7=84=ED=96=89=20=EC=A4=91=EC=9D=B8=EC=A7=80=20?= =?UTF-8?q?=EC=95=84=EB=8B=8C=EC=A7=80=EB=A5=BC=20=EC=A7=81=EA=B4=80?= =?UTF-8?q?=EC=A0=81=EC=9C=BC=EB=A1=9C=20=ED=99=95=EC=9D=B8=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EA=B2=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/session/SessionHeader.tsx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/frontend/src/components/session/SessionHeader.tsx b/frontend/src/components/session/SessionHeader.tsx index 09d1f4d7..71e2ccda 100644 --- a/frontend/src/components/session/SessionHeader.tsx +++ b/frontend/src/components/session/SessionHeader.tsx @@ -1,4 +1,5 @@ import { RoomMetadata } from "@hooks/type/session"; +import { useEffect, useState } from "react"; interface SessionHeaderProps { roomMetadata: RoomMetadata | null; @@ -9,6 +10,19 @@ const SessionHeader = ({ participantsCount, roomMetadata, }: SessionHeaderProps) => { + const [uptime, setUptime] = useState(0); + + useEffect(() => { + if (!roomMetadata?.inProgress) return; + const interval = setInterval(() => { + setUptime((prev) => prev + 1); + }, 1000); + + return () => { + clearInterval(interval); + }; + }, [roomMetadata?.inProgress]); + return (
+ {roomMetadata.inProgress ? ( + + + 스터디 진행 중 {uptime}초 + + ) : ( + + + 스터디 시작 전 + + )} ) : (

아직 세션에 참가하지 않았습니다.

From e7f4f528e50d1718ac0bd2d390500fe8ba4ef9f2 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 16:36:34 +0900 Subject: [PATCH 05/20] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=20=EB=84=98?= =?UTF-8?q?=EA=B8=B0=EA=B8=B0=20API=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8A=A4=ED=84=B0=EB=94=94=20=EC=8B=9C=EC=9E=91=20API=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/SessionPage.tsx | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/SessionPage.tsx b/frontend/src/pages/SessionPage.tsx index ca6f220a..5019c928 100644 --- a/frontend/src/pages/SessionPage.tsx +++ b/frontend/src/pages/SessionPage.tsx @@ -7,6 +7,7 @@ import useSocket from "@hooks/useSocket"; import SessionHeader from "@components/session/SessionHeader"; import { useEffect } from "react"; import useToast from "@hooks/useToast.ts"; +import { STUDY_EMIT_EVENT } from "@/constants/WebSocket/StudyEvent.ts"; const SessionPage = () => { const { sessionId } = useParams(); @@ -42,6 +43,39 @@ const SessionPage = () => { peerMediaStatus, } = useSession(sessionId!); + const requestChangeIndex = ( + type: "next" | "prev" | "current" | "move", + index?: number + ) => { + if (socket) { + if (isHost && roomMetadata) { + switch (type) { + case "next": + socket.emit(STUDY_EMIT_EVENT.NEXT, { roomId: sessionId }); + break; + case "prev": + socket.emit(STUDY_EMIT_EVENT.INDEX, { + roomId: sessionId, + index: roomMetadata.currentIndex - 1, + }); + break; + case "current": + socket.emit(STUDY_EMIT_EVENT.CURRENT, { roomId: sessionId }); + break; + case "move": + socket.emit(STUDY_EMIT_EVENT.INDEX, { roomId: sessionId, index }); + break; + } + } + } + }; + + const startStudySession = () => { + if (socket) { + socket.emit(STUDY_EMIT_EVENT.START, { roomId: sessionId }); + } + }; + return (
@@ -119,6 +153,7 @@ const SessionPage = () => {
{ isVideoOn={isVideoOn} isMicOn={isMicOn} videoLoading={videoLoading} + isHost={isHost} + isInProgress={roomMetadata?.inProgress ?? false} + startStudySession={startStudySession} /> Date: Thu, 28 Nov 2024 16:36:55 +0900 Subject: [PATCH 06/20] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=EC=9D=84=20=ED=91=9C=EC=8B=9C=ED=95=98=EA=B3=A0=20?= =?UTF-8?q?=EC=9D=B4=EC=A0=84=20=EC=A7=88=EB=AC=B8=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=EA=B8=B0=EB=A1=9D=EC=9D=84=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=EB=B0=94=EC=97=90=20=EB=82=A8=EA=B8=B0=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/session/SessionSidebar.tsx | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/session/SessionSidebar.tsx b/frontend/src/components/session/SessionSidebar.tsx index c0f7b23e..36dabde0 100644 --- a/frontend/src/components/session/SessionSidebar.tsx +++ b/frontend/src/components/session/SessionSidebar.tsx @@ -1,4 +1,4 @@ -import { FaClipboardList } from "react-icons/fa"; +import { FaClipboardList, FaFolder } from "react-icons/fa"; import { FaUserGroup } from "react-icons/fa6"; import useModalStore from "../../stores/useModalStore"; import Modal from "../common/Modal"; @@ -7,6 +7,7 @@ import { Socket } from "socket.io-client"; import useToast from "../../hooks/useToast"; import { TbCrown } from "react-icons/tb"; import { SESSION_EMIT_EVENT } from "@/constants/WebSocket/SessionEvent.ts"; +import { Question } from "@hooks/type/session"; interface ParticipantsData { nickname: string; @@ -15,7 +16,8 @@ interface ParticipantsData { interface Props { socket: Socket | null; - question: string; + questionList: Question[]; + currentIndex: number; participants: ParticipantsData[]; roomId: string | undefined; // TODO: sessionId가 입력되지 않았을 때(undefined) 처리 필요 isHost: boolean; @@ -23,7 +25,8 @@ interface Props { const SessionSidebar = ({ socket, - question, + questionList, + currentIndex, participants, roomId, isHost, @@ -94,20 +97,29 @@ const SessionSidebar = ({ />
-

+

- 질문 + 현재 질문

-

- {question} -

+ {currentIndex >= 0 ? ( +

+ + Q{questionList[currentIndex].index}.{" "} + + {questionList[currentIndex].content} +

+ ) : ( +

질문 로딩 중...

+ )} +
-
-

+
+

참가자

@@ -123,6 +135,27 @@ const SessionSidebar = ({ ))}
+
+

+ + 이전 질문 +

+
    + {currentIndex <= 0 && ( +
  • + 여기에 이전 질문이 기록됩니다. +
  • + )} + {questionList.map((question, index) => { + if (index < currentIndex) + return ( +
  • + Q{index + 1}. {question.content} +
  • + ); + })} +
+

- + {isHost && isInProgress ? ( +
+ +
+ ) : ( +
+ +
+ )} + {isHost && isInProgress && ( +
+ + +
+ )}
); }; diff --git a/frontend/src/hooks/session/useSocketEvents.ts b/frontend/src/hooks/session/useSocketEvents.ts index eb92bc12..361170c2 100644 --- a/frontend/src/hooks/session/useSocketEvents.ts +++ b/frontend/src/hooks/session/useSocketEvents.ts @@ -14,6 +14,7 @@ import { ResponseMasterChanged, RoomMetadata, PeerConnection, + ProgressResponse, } from "@hooks/type/session"; import { SIGNAL_EMIT_EVENT, @@ -216,11 +217,16 @@ export const useSocketEvents = ({ } }; - const handleStartProgress = () => { - setRoomMetadata((prev) => ({ ...prev!, inProgress: true })); - }; - const handleStopProgress = () => { - setRoomMetadata((prev) => ({ ...prev!, inProgress: false })); + const handleProgress = (data: ProgressResponse) => { + const { status, inProgress } = data; + + if (status === "success") { + setRoomMetadata((prev) => ({ ...prev!, inProgress: inProgress })); + if (inProgress) toast.success("방장이 스터디를 시작했습니다."); + else toast.error("방장이 스터디를 중지했습니다."); + } else { + toast.error("세션 진행을 시작하지 못했습니다."); + } }; socket.on(SIGNAL_LISTEN_EVENT.OFFER, handleGetOffer); @@ -235,8 +241,8 @@ export const useSocketEvents = ({ socket.on(STUDY_LISTEN_EVENT.INDEX, handleChangeIndex); socket.on(STUDY_LISTEN_EVENT.CURRENT, handleChangeIndex); socket.on(STUDY_LISTEN_EVENT.NEXT, handleChangeIndex); - socket.on(STUDY_LISTEN_EVENT.START, handleStartProgress); - socket.on(STUDY_LISTEN_EVENT.STOP, handleStopProgress); + socket.on(STUDY_LISTEN_EVENT.START, handleProgress); + socket.on(STUDY_LISTEN_EVENT.STOP, handleProgress); socket.on(STUDY_LISTEN_EVENT.PROGRESS, handleRoomProgress); return () => { @@ -252,8 +258,8 @@ export const useSocketEvents = ({ socket.off(STUDY_LISTEN_EVENT.INDEX, handleChangeIndex); socket.off(STUDY_LISTEN_EVENT.CURRENT, handleChangeIndex); socket.off(STUDY_LISTEN_EVENT.NEXT, handleChangeIndex); - socket.off(STUDY_LISTEN_EVENT.START, handleStartProgress); - socket.off(STUDY_LISTEN_EVENT.STOP, handleStopProgress); + socket.off(STUDY_LISTEN_EVENT.START, handleProgress); + socket.off(STUDY_LISTEN_EVENT.STOP, handleProgress); if (reactionTimeouts.current) { Object.values(reactionTimeouts.current).forEach(clearTimeout); diff --git a/frontend/src/hooks/type/session.d.ts b/frontend/src/hooks/type/session.d.ts index a013259a..7d4d8f33 100644 --- a/frontend/src/hooks/type/session.d.ts +++ b/frontend/src/hooks/type/session.d.ts @@ -61,3 +61,8 @@ export interface PeerConnection { isHost?: boolean; // 호스트 여부 reaction?: string; } + +export interface ProgressResponse { + status: "success" | "error"; + inProgress: boolean; +} diff --git a/frontend/src/pages/SessionPage.tsx b/frontend/src/pages/SessionPage.tsx index 5019c928..6c1b9eb6 100644 --- a/frontend/src/pages/SessionPage.tsx +++ b/frontend/src/pages/SessionPage.tsx @@ -76,6 +76,12 @@ const SessionPage = () => { } }; + const stopStudySession = () => { + if (socket) { + socket.emit(STUDY_EMIT_EVENT.STOP, { roomId: sessionId }); + } + }; + return (
@@ -167,6 +173,7 @@ const SessionPage = () => { isHost={isHost} isInProgress={roomMetadata?.inProgress ?? false} startStudySession={startStudySession} + stopStudySession={stopStudySession} />
Date: Thu, 28 Nov 2024 19:51:21 +0900 Subject: [PATCH 09/20] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=EB=B0=94=20=EC=A0=91=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/session/SessionSidebar.tsx | 159 +++++++++--------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/frontend/src/components/session/SessionSidebar.tsx b/frontend/src/components/session/SessionSidebar.tsx index 36dabde0..fe1d22c6 100644 --- a/frontend/src/components/session/SessionSidebar.tsx +++ b/frontend/src/components/session/SessionSidebar.tsx @@ -8,6 +8,7 @@ import useToast from "../../hooks/useToast"; import { TbCrown } from "react-icons/tb"; import { SESSION_EMIT_EVENT } from "@/constants/WebSocket/SessionEvent.ts"; import { Question } from "@hooks/type/session"; +import { BsLayoutSidebarReverse } from "react-icons/bs"; interface ParticipantsData { nickname: string; @@ -70,10 +71,90 @@ const SessionSidebar = ({ return (
+
+ +
+
+
+
+

+ + 현재 질문 +

+
+ {currentIndex >= 0 ? ( +

+ + Q{questionList[currentIndex].index}.{" "} + + {questionList[currentIndex].content} +

+ ) : ( +

질문 로딩 중...

+ )} +
+
+
+

+ + 참가자 +

+
    + {participants.map((participant, index) => ( +
  • + + {participant.nickname} + + {participant.isHost && } + +
  • + ))} +
+
+
+

+ + 이전 질문 +

+
    + {currentIndex <= 0 && ( +
  • + 여기에 이전 질문이 기록됩니다. +
  • + )} + {questionList.map((question, index) => { + if (index < currentIndex) + return ( +
  • + Q{index + 1}. {question.content} +
  • + ); + })} +
+
+
+
+ +
+
+ -
-
-

- - 현재 질문 -

-
- {currentIndex >= 0 ? ( -

- - Q{questionList[currentIndex].index}.{" "} - - {questionList[currentIndex].content} -

- ) : ( -

질문 로딩 중...

- )} -
-
-
-

- - 참가자 -

-
    - {participants.map((participant, index) => ( -
  • - - {participant.nickname} - - {participant.isHost && } - -
  • - ))} -
-
-
-

- - 이전 질문 -

-
    - {currentIndex <= 0 && ( -
  • - 여기에 이전 질문이 기록됩니다. -
  • - )} - {questionList.map((question, index) => { - if (index < currentIndex) - return ( -
  • - Q{index + 1}. {question.content} -
  • - ); - })} -
-
-
-
- -
); }; From b1af3f15e667aabb70d2f0a6ef986c894bd558d1 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 20:43:30 +0900 Subject: [PATCH 10/20] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=EB=B0=94=EB=A5=BC=20=EC=A0=91=EC=9D=84=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=82=AC=EC=9D=B4=EB=93=9C=EB=B0=94?= =?UTF-8?q?=EB=A5=BC=20=EA=B0=90=EC=8B=B8=EB=8A=94=20Container=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/session/SessionSidebar.tsx | 12 ++----- .../SessionSidebar/SidebarContainer.tsx | 32 +++++++++++++++++++ frontend/src/pages/SessionPage.tsx | 19 ++++++----- 3 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 frontend/src/components/session/SessionSidebar/SidebarContainer.tsx diff --git a/frontend/src/components/session/SessionSidebar.tsx b/frontend/src/components/session/SessionSidebar.tsx index fe1d22c6..524175d7 100644 --- a/frontend/src/components/session/SessionSidebar.tsx +++ b/frontend/src/components/session/SessionSidebar.tsx @@ -8,7 +8,6 @@ import useToast from "../../hooks/useToast"; import { TbCrown } from "react-icons/tb"; import { SESSION_EMIT_EVENT } from "@/constants/WebSocket/SessionEvent.ts"; import { Question } from "@hooks/type/session"; -import { BsLayoutSidebarReverse } from "react-icons/bs"; interface ParticipantsData { nickname: string; @@ -71,15 +70,10 @@ const SessionSidebar = ({ return (
-
- -
diff --git a/frontend/src/components/session/SessionSidebar/SidebarContainer.tsx b/frontend/src/components/session/SessionSidebar/SidebarContainer.tsx new file mode 100644 index 00000000..6b1cf96e --- /dev/null +++ b/frontend/src/components/session/SessionSidebar/SidebarContainer.tsx @@ -0,0 +1,32 @@ +import { ReactNode, useState } from "react"; +import { FaArrowLeft } from "react-icons/fa"; + +interface SidebarContainerProps { + children: ReactNode; +} + +const SidebarContainer = ({ children }: SidebarContainerProps) => { + const [isCollapsed, setIsCollapsed] = useState(false); + return ( +
+
+ {children} +
+ +
+ ); +}; + +export default SidebarContainer; diff --git a/frontend/src/pages/SessionPage.tsx b/frontend/src/pages/SessionPage.tsx index 6c1b9eb6..5a324fa1 100644 --- a/frontend/src/pages/SessionPage.tsx +++ b/frontend/src/pages/SessionPage.tsx @@ -8,6 +8,7 @@ import SessionHeader from "@components/session/SessionHeader"; import { useEffect } from "react"; import useToast from "@hooks/useToast.ts"; import { STUDY_EMIT_EVENT } from "@/constants/WebSocket/StudyEvent.ts"; +import SidebarContainer from "@components/session/SessionSidebar/SidebarContainer.tsx"; const SessionPage = () => { const { sessionId } = useParams(); @@ -176,14 +177,16 @@ const SessionPage = () => { stopStudySession={stopStudySession} />
- + + +
); From 37f234c7894261e3bcb462dc6f3d55c5a500a219 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 20:44:44 +0900 Subject: [PATCH 11/20] =?UTF-8?q?chore:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=ED=81=B0=20=EB=8B=A8=EC=9C=84=EB=A1=9C=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/session/{ => Sidebar}/SessionSidebar.tsx | 6 +++--- .../{SessionSidebar => Sidebar}/SidebarContainer.tsx | 0 .../src/components/session/{ => Toolbar}/SessionToolbar.tsx | 0 frontend/src/pages/SessionPage.tsx | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) rename frontend/src/components/session/{ => Sidebar}/SessionSidebar.tsx (97%) rename frontend/src/components/session/{SessionSidebar => Sidebar}/SidebarContainer.tsx (100%) rename frontend/src/components/session/{ => Toolbar}/SessionToolbar.tsx (100%) diff --git a/frontend/src/components/session/SessionSidebar.tsx b/frontend/src/components/session/Sidebar/SessionSidebar.tsx similarity index 97% rename from frontend/src/components/session/SessionSidebar.tsx rename to frontend/src/components/session/Sidebar/SessionSidebar.tsx index 524175d7..5bcc1b95 100644 --- a/frontend/src/components/session/SessionSidebar.tsx +++ b/frontend/src/components/session/Sidebar/SessionSidebar.tsx @@ -1,10 +1,10 @@ import { FaClipboardList, FaFolder } from "react-icons/fa"; import { FaUserGroup } from "react-icons/fa6"; -import useModalStore from "../../stores/useModalStore"; -import Modal from "../common/Modal"; +import useModalStore from "@stores/useModalStore.ts"; +import Modal from "../../common/Modal"; import { useNavigate } from "react-router-dom"; import { Socket } from "socket.io-client"; -import useToast from "../../hooks/useToast"; +import useToast from "@hooks/useToast.ts"; import { TbCrown } from "react-icons/tb"; import { SESSION_EMIT_EVENT } from "@/constants/WebSocket/SessionEvent.ts"; import { Question } from "@hooks/type/session"; diff --git a/frontend/src/components/session/SessionSidebar/SidebarContainer.tsx b/frontend/src/components/session/Sidebar/SidebarContainer.tsx similarity index 100% rename from frontend/src/components/session/SessionSidebar/SidebarContainer.tsx rename to frontend/src/components/session/Sidebar/SidebarContainer.tsx diff --git a/frontend/src/components/session/SessionToolbar.tsx b/frontend/src/components/session/Toolbar/SessionToolbar.tsx similarity index 100% rename from frontend/src/components/session/SessionToolbar.tsx rename to frontend/src/components/session/Toolbar/SessionToolbar.tsx diff --git a/frontend/src/pages/SessionPage.tsx b/frontend/src/pages/SessionPage.tsx index 5a324fa1..26c9de8d 100644 --- a/frontend/src/pages/SessionPage.tsx +++ b/frontend/src/pages/SessionPage.tsx @@ -1,14 +1,14 @@ import VideoContainer from "@components/session/VideoContainer.tsx"; import { useParams } from "react-router-dom"; -import SessionSidebar from "@components/session/SessionSidebar.tsx"; -import SessionToolbar from "@components/session/SessionToolbar.tsx"; +import SessionSidebar from "@components/session/Sidebar/SessionSidebar.tsx"; +import SessionToolbar from "@components/session/Toolbar/SessionToolbar.tsx"; import { useSession } from "@hooks/session/useSession"; import useSocket from "@hooks/useSocket"; import SessionHeader from "@components/session/SessionHeader"; import { useEffect } from "react"; import useToast from "@hooks/useToast.ts"; import { STUDY_EMIT_EVENT } from "@/constants/WebSocket/StudyEvent.ts"; -import SidebarContainer from "@components/session/SessionSidebar/SidebarContainer.tsx"; +import SidebarContainer from "@components/session/Sidebar/SidebarContainer.tsx"; const SessionPage = () => { const { sessionId } = useParams(); From 4834f7824ff7162f1fcead6dbb5ac48d9e5ce824 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 20:52:19 +0900 Subject: [PATCH 12/20] =?UTF-8?q?refactor:=20=ED=98=B8=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A7=8C=20=EC=82=AC=EC=9A=A9=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EB=8F=84=EA=B5=AC=EC=99=80=20=EC=9D=BC=EB=B0=98=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EB=93=A4=EB=8F=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20=EB=8F=84=EA=B5=AC?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컴포넌트 폴더에 하위 폴더를 만들어 구분 --- .../session/Toolbar/CommonTools.tsx | 95 +++++++++++++ .../session/Toolbar/HostOnlyTools.tsx | 71 ++++++++++ .../session/Toolbar/SessionToolbar.tsx | 130 +++--------------- 3 files changed, 187 insertions(+), 109 deletions(-) create mode 100644 frontend/src/components/session/Toolbar/CommonTools.tsx create mode 100644 frontend/src/components/session/Toolbar/HostOnlyTools.tsx diff --git a/frontend/src/components/session/Toolbar/CommonTools.tsx b/frontend/src/components/session/Toolbar/CommonTools.tsx new file mode 100644 index 00000000..3badd676 --- /dev/null +++ b/frontend/src/components/session/Toolbar/CommonTools.tsx @@ -0,0 +1,95 @@ +import { + BsCameraVideo, + BsCameraVideoOff, + BsHandThumbsUp, + BsMic, + BsMicMute, +} from "react-icons/bs"; + +interface CommonToolsProps { + handleVideoToggle: () => void; + handleMicToggle: () => void; + emitReaction: (reactionType: string) => void; + userVideoDevices: MediaDeviceInfo[]; + userAudioDevices: MediaDeviceInfo[]; + setSelectedVideoDeviceId: (deviceId: string) => void; + setSelectedAudioDeviceId: (deviceId: string) => void; + isVideoOn: boolean; + isMicOn: boolean; + videoLoading: boolean; +} +const CommonTools = ({ + handleVideoToggle, + handleMicToggle, + emitReaction, + userVideoDevices, + userAudioDevices, + setSelectedVideoDeviceId, + setSelectedAudioDeviceId, + isVideoOn, + isMicOn, + videoLoading, +}: CommonToolsProps) => { + return ( + <> +
+ + + + + +
+ + ); +}; + +export default CommonTools; diff --git a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx new file mode 100644 index 00000000..ce3d20eb --- /dev/null +++ b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx @@ -0,0 +1,71 @@ +import { FaAngleLeft, FaAngleRight } from "react-icons/fa6"; + +// 툴바에서 호스트만 사용가능 도구들 분리 +interface HostOnlyToolsProps { + isHost: boolean; + isInProgress: boolean; + stopStudySession: () => void; + startStudySession: () => void; + requestChangeIndex: (type: "next" | "prev") => void; +} +const HostOnlyTools = ({ + isHost, + isInProgress, + stopStudySession, + startStudySession, + requestChangeIndex, +}: HostOnlyToolsProps) => { + return ( + isHost && ( + <> + {isInProgress ? ( +
+ +
+ ) : ( +
+ +
+ )} + {isInProgress && ( +
+ + +
+ )} + + ) + ); +}; + +export default HostOnlyTools; diff --git a/frontend/src/components/session/Toolbar/SessionToolbar.tsx b/frontend/src/components/session/Toolbar/SessionToolbar.tsx index b686b82e..4a6a8f10 100644 --- a/frontend/src/components/session/Toolbar/SessionToolbar.tsx +++ b/frontend/src/components/session/Toolbar/SessionToolbar.tsx @@ -1,11 +1,5 @@ -import { FaAngleLeft, FaAngleRight } from "react-icons/fa6"; -import { - BsCameraVideo, - BsCameraVideoOff, - BsMic, - BsMicMute, - BsHandThumbsUp, -} from "react-icons/bs"; +import HostOnlyTools from "@components/session/Toolbar/HostOnlyTools.tsx"; +import CommonTools from "@components/session/Toolbar/CommonTools.tsx"; interface Props { requestChangeIndex: ( @@ -50,107 +44,25 @@ const SessionToolbar = ({ "session-footer h-16 inline-flex w-full justify-center items-center border-t px-6 shrink-0" } > -
- - - - - -
- {isHost && isInProgress ? ( -
- -
- ) : ( -
- -
- )} - {isHost && isInProgress && ( -
- - -
- )} + + ); }; From e1c3588f9239bd51a5c258a93db5381bfac7f6ce Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 20:55:08 +0900 Subject: [PATCH 13/20] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EC=8B=9C=EC=9E=91=ED=95=98=EB=A9=B4=20=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=EC=9D=B8=EB=94=94=EC=BC=80=EC=9D=B4=ED=84=B0=EB=A5=BC=20?= =?UTF-8?q?=EB=9D=84=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/session/SessionHeader.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/session/SessionHeader.tsx b/frontend/src/components/session/SessionHeader.tsx index 71e2ccda..9fb85966 100644 --- a/frontend/src/components/session/SessionHeader.tsx +++ b/frontend/src/components/session/SessionHeader.tsx @@ -41,11 +41,14 @@ const SessionHeader = ({ `(${participantsCount} / ${roomMetadata.maxParticipants})`} {roomMetadata.inProgress ? ( - + - 스터디 진행 중 {uptime}초 + 스터디 진행 중 + {uptime}초 ) : ( From dde42e08f0761a25f00f3cd97816ca1d1432e11c Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 21:06:58 +0900 Subject: [PATCH 14/20] =?UTF-8?q?feat:=20=EB=8B=A4=EC=9D=8C=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8,=20=EC=9D=B4=EC=A0=84=20=EC=A7=88=EB=AC=B8=20?= =?UTF-8?q?=EB=88=84=EB=A5=B4=EA=B3=A0=202=EC=B4=88=20=ED=9B=84=EC=97=90?= =?UTF-8?q?=20=ED=99=9C=EC=84=B1=ED=99=94=20=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../session/Toolbar/HostOnlyTools.tsx | 54 ++++++++++++++++--- frontend/src/index.css | 6 +++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx index ce3d20eb..dcb5faf1 100644 --- a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx +++ b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx @@ -1,4 +1,5 @@ import { FaAngleLeft, FaAngleRight } from "react-icons/fa6"; +import { useEffect, useState } from "react"; // 툴바에서 호스트만 사용가능 도구들 분리 interface HostOnlyToolsProps { @@ -15,6 +16,21 @@ const HostOnlyTools = ({ startStudySession, requestChangeIndex, }: HostOnlyToolsProps) => { + const [changeCooldown, setChangeCooldown] = useState(false); + const COOLDOWN_TIME = 2000; + + useEffect(() => { + if (!changeCooldown) return; + + const timeout = setTimeout(() => { + setChangeCooldown(false); + }, COOLDOWN_TIME); + + return () => { + clearTimeout(timeout); + }; + }, [changeCooldown]); + return ( isHost && ( <> @@ -24,7 +40,9 @@ const HostOnlyTools = ({ className={ "bg-transparent rounded-xl border h-10 px-3 py-2 text-medium-xs " } - onClick={stopStudySession} + onClick={() => { + stopStudySession(); + }} > 스터디 종료하기 @@ -35,7 +53,9 @@ const HostOnlyTools = ({ className={ "bg-transparent rounded-xl border h-10 px-3 py-2 text-medium-xs " } - onClick={startStudySession} + onClick={() => { + startStudySession(); + }} > 스터디 시작하기 @@ -44,22 +64,44 @@ const HostOnlyTools = ({ {isInProgress && (
)} diff --git a/frontend/src/index.css b/frontend/src/index.css index c6b4bbb4..31fb23af 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -56,6 +56,12 @@ } } +.animate-progress { + animation: expand 2s ease; + animation-iteration-count: 1; + animation-timing-function: linear; +} + .revealExpand { animation: revealExpand 0.2s ease; animation-iteration-count: 1; From 6e96862015b0ae9523f1e77a3913fd9107b62cdd Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 21:09:36 +0900 Subject: [PATCH 15/20] =?UTF-8?q?fix:=20=EC=A7=88=EB=AC=B8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EA=B0=80=20=EC=9E=98=EB=AA=BB=EB=90=98=EC=96=B4?= =?UTF-8?q?=EC=9E=88=EB=8D=98=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/session/Sidebar/SessionSidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/session/Sidebar/SessionSidebar.tsx b/frontend/src/components/session/Sidebar/SessionSidebar.tsx index 5bcc1b95..3b9e1606 100644 --- a/frontend/src/components/session/Sidebar/SessionSidebar.tsx +++ b/frontend/src/components/session/Sidebar/SessionSidebar.tsx @@ -89,7 +89,7 @@ const SessionSidebar = ({ {currentIndex >= 0 ? (

- Q{questionList[currentIndex].index}.{" "} + Q{questionList[currentIndex].index + 1}.{" "} {questionList[currentIndex].content}

From 431d9bc0b0823d347216631a2d162f7935f87649 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 21:09:54 +0900 Subject: [PATCH 16/20] =?UTF-8?q?fix:=20=EB=B2=84=ED=8A=BC=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EB=A0=88=EC=8A=A4=EB=B0=94=EA=B0=80=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=ED=98=84=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/session/Toolbar/HostOnlyTools.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx index dcb5faf1..c3e40ea0 100644 --- a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx +++ b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx @@ -69,7 +69,7 @@ const HostOnlyTools = ({ setChangeCooldown(true); }} className={ - "relative inline-flex items-center bg-transparent rounded-xl border h-10 px-3 py-2 text-medium-xs disabled:opacity-50" + "relative inline-flex items-center bg-transparent rounded-xl border h-10 px-3 py-2 text-medium-xs disabled:opacity-50 overflow-hidden" } aria-label={"이전 질문 버튼"} disabled={changeCooldown} From 582171dd5f3180a3b4e3ea5e1f27d04b76b68a3b Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 21:56:36 +0900 Subject: [PATCH 17/20] =?UTF-8?q?refactor:=20study=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20useStudy=20=ED=9B=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/session/useSession.ts | 11 ++++++ frontend/src/hooks/session/useStudy.ts | 46 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 frontend/src/hooks/session/useStudy.ts diff --git a/frontend/src/hooks/session/useSession.ts b/frontend/src/hooks/session/useSession.ts index 7670ff27..85f1d8d1 100644 --- a/frontend/src/hooks/session/useSession.ts +++ b/frontend/src/hooks/session/useSession.ts @@ -11,6 +11,7 @@ import { useSocketEvents } from "./useSocketEvents"; import { Socket } from "socket.io-client"; import { SESSION_EMIT_EVENT } from "@/constants/WebSocket/SessionEvent"; import useAuth from "@hooks/useAuth"; +import useStudy from "@hooks/session/useStudy"; export const useSession = (sessionId: string) => { const { socket } = useSocket(); @@ -67,6 +68,13 @@ export const useSession = (sessionId: string) => { setPeers ); + const { requestChangeIndex, stopStudySession, startStudySession } = useStudy( + socket, + sessionId, + setRoomMetadata, + setPeers + ); + useSocketEvents({ socket, stream, @@ -153,5 +161,8 @@ export const useSession = (sessionId: string) => { emitReaction, videoLoading, peerMediaStatus, + requestChangeIndex, + startStudySession, + stopStudySession, }; }; diff --git a/frontend/src/hooks/session/useStudy.ts b/frontend/src/hooks/session/useStudy.ts new file mode 100644 index 00000000..eff50d71 --- /dev/null +++ b/frontend/src/hooks/session/useStudy.ts @@ -0,0 +1,46 @@ +import { STUDY_EMIT_EVENT } from "@/constants/WebSocket/StudyEvent.ts"; + +const useStudy = (socket, isHost, roomMetadata, sessionId) => { + const requestChangeIndex = ( + type: "next" | "prev" | "current" | "move", + index?: number + ) => { + if (socket) { + if (isHost && roomMetadata) { + switch (type) { + case "next": + socket.emit(STUDY_EMIT_EVENT.NEXT, { roomId: sessionId }); + break; + case "prev": + socket.emit(STUDY_EMIT_EVENT.INDEX, { + roomId: sessionId, + index: roomMetadata.currentIndex - 1, + }); + break; + case "current": + socket.emit(STUDY_EMIT_EVENT.CURRENT, { roomId: sessionId }); + break; + case "move": + socket.emit(STUDY_EMIT_EVENT.INDEX, { roomId: sessionId, index }); + break; + } + } + } + }; + + const startStudySession = () => { + if (socket) { + socket.emit(STUDY_EMIT_EVENT.START, { roomId: sessionId }); + } + }; + + const stopStudySession = () => { + if (socket) { + socket.emit(STUDY_EMIT_EVENT.STOP, { roomId: sessionId }); + } + }; + + return { requestChangeIndex, startStudySession, stopStudySession }; +}; + +export default useStudy; From 966d140987de3e8594789160d316c5323b49a502 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 21:59:49 +0900 Subject: [PATCH 18/20] =?UTF-8?q?refactor:=20uptime=20=EB=B6=84/=EC=B4=88?= =?UTF-8?q?=EB=A1=9C=20=ED=91=9C=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/session/SessionHeader.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/session/SessionHeader.tsx b/frontend/src/components/session/SessionHeader.tsx index 9fb85966..e336ca9e 100644 --- a/frontend/src/components/session/SessionHeader.tsx +++ b/frontend/src/components/session/SessionHeader.tsx @@ -11,12 +11,12 @@ const SessionHeader = ({ roomMetadata, }: SessionHeaderProps) => { const [uptime, setUptime] = useState(0); - + const SECOND = 1000; useEffect(() => { if (!roomMetadata?.inProgress) return; const interval = setInterval(() => { setUptime((prev) => prev + 1); - }, 1000); + }, SECOND); return () => { clearInterval(interval); @@ -31,7 +31,6 @@ const SessionHeader = ({ > {roomMetadata?.title ? ( <> - {" "} {roomMetadata?.category} @@ -48,7 +47,9 @@ const SessionHeader = ({ } >
스터디 진행 중 - {uptime}초 + + {Math.floor(uptime / 60)}분 {uptime % 60}초 +
) : ( From cac93ce9bb2d2b8340c2d4b0e7ace7f1515176e9 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 22:00:51 +0900 Subject: [PATCH 19/20] =?UTF-8?q?refactor:=20useStudy=20->=20useSession?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B0=9B=EC=95=84=EC=98=A8=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/SessionPage.tsx | 43 +++--------------------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/frontend/src/pages/SessionPage.tsx b/frontend/src/pages/SessionPage.tsx index 26c9de8d..cc473159 100644 --- a/frontend/src/pages/SessionPage.tsx +++ b/frontend/src/pages/SessionPage.tsx @@ -7,7 +7,6 @@ import useSocket from "@hooks/useSocket"; import SessionHeader from "@components/session/SessionHeader"; import { useEffect } from "react"; import useToast from "@hooks/useToast.ts"; -import { STUDY_EMIT_EVENT } from "@/constants/WebSocket/StudyEvent.ts"; import SidebarContainer from "@components/session/Sidebar/SidebarContainer.tsx"; const SessionPage = () => { @@ -42,47 +41,11 @@ const SessionPage = () => { emitReaction, videoLoading, peerMediaStatus, + requestChangeIndex, + startStudySession, + stopStudySession, } = useSession(sessionId!); - const requestChangeIndex = ( - type: "next" | "prev" | "current" | "move", - index?: number - ) => { - if (socket) { - if (isHost && roomMetadata) { - switch (type) { - case "next": - socket.emit(STUDY_EMIT_EVENT.NEXT, { roomId: sessionId }); - break; - case "prev": - socket.emit(STUDY_EMIT_EVENT.INDEX, { - roomId: sessionId, - index: roomMetadata.currentIndex - 1, - }); - break; - case "current": - socket.emit(STUDY_EMIT_EVENT.CURRENT, { roomId: sessionId }); - break; - case "move": - socket.emit(STUDY_EMIT_EVENT.INDEX, { roomId: sessionId, index }); - break; - } - } - } - }; - - const startStudySession = () => { - if (socket) { - socket.emit(STUDY_EMIT_EVENT.START, { roomId: sessionId }); - } - }; - - const stopStudySession = () => { - if (socket) { - socket.emit(STUDY_EMIT_EVENT.STOP, { roomId: sessionId }); - } - }; - return (
From d950de1a15a7fe0c5587a87890ab7c548d524739 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Thu, 28 Nov 2024 22:04:43 +0900 Subject: [PATCH 20/20] =?UTF-8?q?refactor:=20=EC=9D=B4=EC=A0=84=20?= =?UTF-8?q?=EC=A7=88=EB=AC=B8=20=EB=B2=84=ED=8A=BC=EA=B3=BC=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=8C=20=EC=A7=88=EB=AC=B8=20=EB=B2=84=ED=8A=BC=EC=9D=B4=20?= =?UTF-8?q?=EC=A7=88=EB=AC=B8=EC=A7=80=EC=9D=98=20=EC=96=91=20=EB=81=9D?= =?UTF-8?q?=EB=8B=A8=EC=97=90=EC=84=9C=20=EB=B9=84=ED=99=9C=EC=84=B1?= =?UTF-8?q?=ED=99=94=EB=90=98=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/session/Toolbar/HostOnlyTools.tsx | 10 ++++++++-- .../src/components/session/Toolbar/SessionToolbar.tsx | 6 ++++++ frontend/src/pages/SessionPage.tsx | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx index c3e40ea0..72f2ac74 100644 --- a/frontend/src/components/session/Toolbar/HostOnlyTools.tsx +++ b/frontend/src/components/session/Toolbar/HostOnlyTools.tsx @@ -8,6 +8,8 @@ interface HostOnlyToolsProps { stopStudySession: () => void; startStudySession: () => void; requestChangeIndex: (type: "next" | "prev") => void; + currentIndex: number; + maxQuestionLength: number; } const HostOnlyTools = ({ isHost, @@ -15,6 +17,8 @@ const HostOnlyTools = ({ stopStudySession, startStudySession, requestChangeIndex, + currentIndex, + maxQuestionLength, }: HostOnlyToolsProps) => { const [changeCooldown, setChangeCooldown] = useState(false); const COOLDOWN_TIME = 2000; @@ -72,7 +76,7 @@ const HostOnlyTools = ({ "relative inline-flex items-center bg-transparent rounded-xl border h-10 px-3 py-2 text-medium-xs disabled:opacity-50 overflow-hidden" } aria-label={"이전 질문 버튼"} - disabled={changeCooldown} + disabled={changeCooldown || currentIndex === 0} > 이전 질문 {changeCooldown && ( @@ -92,7 +96,9 @@ const HostOnlyTools = ({ "relative inline-flex items-center bg-transparent rounded-xl border h-10 px-3 py-2 text-medium-xs disabled:opacity-50 overflow-hidden" } aria-label={"다음 질문 버튼"} - disabled={changeCooldown} + disabled={ + changeCooldown || currentIndex === maxQuestionLength - 1 + } > 다음 질문 {changeCooldown && ( diff --git a/frontend/src/components/session/Toolbar/SessionToolbar.tsx b/frontend/src/components/session/Toolbar/SessionToolbar.tsx index 4a6a8f10..f7c0ab48 100644 --- a/frontend/src/components/session/Toolbar/SessionToolbar.tsx +++ b/frontend/src/components/session/Toolbar/SessionToolbar.tsx @@ -20,6 +20,8 @@ interface Props { isInProgress: boolean; startStudySession: () => void; stopStudySession: () => void; + currentIndex: number; + maxQuestionLength: number; } const SessionToolbar = ({ requestChangeIndex, @@ -37,6 +39,8 @@ const SessionToolbar = ({ isInProgress, startStudySession, stopStudySession, + currentIndex, + maxQuestionLength, }: Props) => { return (
); diff --git a/frontend/src/pages/SessionPage.tsx b/frontend/src/pages/SessionPage.tsx index cc473159..89d395bf 100644 --- a/frontend/src/pages/SessionPage.tsx +++ b/frontend/src/pages/SessionPage.tsx @@ -138,6 +138,8 @@ const SessionPage = () => { isInProgress={roomMetadata?.inProgress ?? false} startStudySession={startStudySession} stopStudySession={stopStudySession} + currentIndex={roomMetadata?.currentIndex ?? -1} + maxQuestionLength={roomMetadata?.questionListContents.length ?? 0} />