From 979c3895d0452d422eb2ac253332a6ed2bb10ac0 Mon Sep 17 00:00:00 2001 From: Shogo Nakamura <104970808+naka-12@users.noreply.github.com> Date: Fri, 11 Apr 2025 23:57:20 +0900 Subject: [PATCH 1/8] =?UTF-8?q?pwa=20manifest=20=E3=81=AE=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=20(#687)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/lib/panic.ts | 8 +++++--- web/app/manifest.ts | 25 +++++++++++++++++++++++++ web/public/icon-192x192.png | Bin 0 -> 3330 bytes web/public/icon-512x512.png | Bin 0 -> 13039 bytes 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 web/app/manifest.ts create mode 100644 web/public/icon-192x192.png create mode 100644 web/public/icon-512x512.png diff --git a/common/lib/panic.ts b/common/lib/panic.ts index 0a7ae204..63afe954 100644 --- a/common/lib/panic.ts +++ b/common/lib/panic.ts @@ -1,6 +1,8 @@ // unexpected error export function panic(reason: string): never { - throw new Error(reason, { - cause: "panic", - }); + throw new Error(reason); + // TODO: 型エラーとなるため一時的にコメントアウト + // throw new Error(reason, { + // cause: "panic", + // }); } diff --git a/web/app/manifest.ts b/web/app/manifest.ts new file mode 100644 index 00000000..5a875092 --- /dev/null +++ b/web/app/manifest.ts @@ -0,0 +1,25 @@ +import type { MetadataRoute } from "next"; + +export default function manifest(): MetadataRoute.Manifest { + return { + name: "CourseMate", + short_name: "CourseMate", + description: "同じ授業を履修している友達を見つけられるアプリ", + start_url: "/", + display: "standalone", + background_color: "#ffffff", + theme_color: "#000000", + icons: [ + { + src: "/icon-192x192.png", + sizes: "192x192", + type: "image/png", + }, + { + src: "/icon-512x512.png", + sizes: "512x512", + type: "image/png", + }, + ], + }; +} diff --git a/web/public/icon-192x192.png b/web/public/icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..821e0465b5afe697ea63287e684bb33644c7ec45 GIT binary patch literal 3330 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 literal 0 HcmV?d00001 diff --git a/web/public/icon-512x512.png b/web/public/icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..518d10a948e534a38445c2f08c796b54fc8cab0a GIT binary patch literal 13039 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 Date: Sat, 12 Apr 2025 00:07:46 +0900 Subject: [PATCH 2/8] =?UTF-8?q?pwa=20theme=20color=20=E3=82=92=E7=99=BD?= =?UTF-8?q?=E3=81=AB=20(#688)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/app/manifest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/manifest.ts b/web/app/manifest.ts index 5a875092..84e0b73f 100644 --- a/web/app/manifest.ts +++ b/web/app/manifest.ts @@ -8,7 +8,7 @@ export default function manifest(): MetadataRoute.Manifest { start_url: "/", display: "standalone", background_color: "#ffffff", - theme_color: "#000000", + theme_color: "#ffffff", icons: [ { src: "/icon-192x192.png", From 3dcf940daf6e08850ce10cb30ea99540cb5a0560 Mon Sep 17 00:00:00 2001 From: Shogo Nakamura <104970808+naka-12@users.noreply.github.com> Date: Sat, 12 Apr 2025 00:36:50 +0900 Subject: [PATCH 3/8] set safe area (#689) --- web/components/BottomBar.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/components/BottomBar.tsx b/web/components/BottomBar.tsx index b644eb15..14ab9ade 100644 --- a/web/components/BottomBar.tsx +++ b/web/components/BottomBar.tsx @@ -36,7 +36,12 @@ function BottomBarCell({ export default function BottomBar(props: Props) { const { activeTab } = props; return ( -
+
Date: Sun, 13 Apr 2025 02:27:00 +0900 Subject: [PATCH 4/8] =?UTF-8?q?Safe=20Area=20=E5=AF=BE=E5=BF=9C=E3=81=AE?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/app/chat/layout.tsx | 4 ++- web/app/friends/layout.tsx | 4 ++- web/app/globals.css | 5 ++++ web/app/home/layout.tsx | 2 +- web/app/layout.tsx | 53 +++++++----------------------------- web/app/search/layout.tsx | 4 ++- web/app/settings/layout.tsx | 4 ++- web/components/BottomBar.tsx | 3 +- web/components/Providers.tsx | 42 ++++++++++++++++++++++++++++ 9 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 web/components/Providers.tsx diff --git a/web/app/chat/layout.tsx b/web/app/chat/layout.tsx index fabe653b..31bd4e2b 100644 --- a/web/app/chat/layout.tsx +++ b/web/app/chat/layout.tsx @@ -9,7 +9,9 @@ export default function Layout({ children }: { children: React.ReactNode }) {
-
{children}
+
+ {children} +
diff --git a/web/app/friends/layout.tsx b/web/app/friends/layout.tsx index 0146483c..721d92db 100644 --- a/web/app/friends/layout.tsx +++ b/web/app/friends/layout.tsx @@ -9,7 +9,9 @@ export default function Layout({ children }: { children: React.ReactNode }) {
-
{children}
+
+ {children} +
diff --git a/web/app/globals.css b/web/app/globals.css index fe4c7bb8..d0c12603 100644 --- a/web/app/globals.css +++ b/web/app/globals.css @@ -11,3 +11,8 @@ .cm-li-btn { @apply no-animation h-auto w-full justify-start rounded-none border-none bg-white px-6 py-4 text-left font-normal text-base shadow-none hover:bg-zinc-100 focus:bg-zinc-300; } + +/* Bottom Bar の分の幅 */ +.cm-pb-footer { + padding-bottom: calc(3rem + env(safe-area-inset-bottom)); +} diff --git a/web/app/home/layout.tsx b/web/app/home/layout.tsx index ec50a110..cfb28d1f 100644 --- a/web/app/home/layout.tsx +++ b/web/app/home/layout.tsx @@ -11,7 +11,7 @@ export default function Layout({ <>
-
{children}
+
{children}
diff --git a/web/app/layout.tsx b/web/app/layout.tsx index f6ceb29d..0033c5fa 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -1,62 +1,29 @@ -"use client"; - -import { CssBaseline, ThemeProvider, createTheme } from "@mui/material"; -import { SnackbarProvider } from "notistack"; -import React from "react"; +import type React from "react"; import "./globals.css"; import "@fontsource/roboto/300.css"; import "@fontsource/roboto/400.css"; import "@fontsource/roboto/500.css"; import "@fontsource/roboto/700.css"; -import BanLandscape from "~/components/BanLandscape"; -import SSEProvider from "~/components/SSEProvider"; -import { AlertProvider } from "~/components/common/alert/AlertProvider"; +import type { Viewport } from "next"; +import Providers from "~/components/Providers"; -const theme = createTheme({ - palette: { - primary: { - main: "#039BE5", - }, - secondary: { - main: "#E9F8FF", - }, - }, -}); +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + viewportFit: "cover", +}; export default function RootLayout({ children, -}: { - children: React.ReactNode; -}) { +}: { children: React.ReactNode }) { return ( - - CourseMate - - - - - - - {/* */} - - {children} - {/* */} - - - - + {children} ); diff --git a/web/app/search/layout.tsx b/web/app/search/layout.tsx index 87bbc6a3..8f275579 100644 --- a/web/app/search/layout.tsx +++ b/web/app/search/layout.tsx @@ -9,7 +9,9 @@ export default function Layout({ children }: { children: React.ReactNode }) {
-
{children}
+
+ {children} +
diff --git a/web/app/settings/layout.tsx b/web/app/settings/layout.tsx index 0dfbe9fc..f3d9fa7a 100644 --- a/web/app/settings/layout.tsx +++ b/web/app/settings/layout.tsx @@ -11,7 +11,9 @@ export default function Layout({ <>
-
{children}
+
+ {children} +
diff --git a/web/components/BottomBar.tsx b/web/components/BottomBar.tsx index 14ab9ade..e1694695 100644 --- a/web/components/BottomBar.tsx +++ b/web/components/BottomBar.tsx @@ -37,8 +37,9 @@ export default function BottomBar(props: Props) { const { activeTab } = props; return (
diff --git a/web/components/Providers.tsx b/web/components/Providers.tsx new file mode 100644 index 00000000..250280fa --- /dev/null +++ b/web/components/Providers.tsx @@ -0,0 +1,42 @@ +"use client"; + +import { CssBaseline, ThemeProvider, createTheme } from "@mui/material"; +import { SnackbarProvider } from "notistack"; +import React from "react"; +import type { ReactNode } from "react"; +import BanLandscape from "~/components/BanLandscape"; +import SSEProvider from "~/components/SSEProvider"; +import { AlertProvider } from "~/components/common/alert/AlertProvider"; + +const theme = createTheme({ + palette: { + primary: { + main: "#039BE5", + }, + secondary: { + main: "#E9F8FF", + }, + }, +}); + +export default function Providers({ children }: { children: ReactNode }) { + return ( + + + + + + + {/* */} + + {children} + {/* */} + + + + + ); +} From f224eedf68bc8a2380e858b26ca4791f791f740a Mon Sep 17 00:00:00 2001 From: naka-12 <104970808+naka-12@users.noreply.github.com> Date: Sun, 13 Apr 2025 14:50:56 +0900 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E3=83=99=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E7=89=88=E8=A1=A8=E8=A8=98=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/app/layout.tsx | 11 ++++++----- web/components/Header.tsx | 37 +++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 0033c5fa..3cfd693b 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -4,7 +4,7 @@ import "@fontsource/roboto/300.css"; import "@fontsource/roboto/400.css"; import "@fontsource/roboto/500.css"; import "@fontsource/roboto/700.css"; -import type { Viewport } from "next"; +import type { Metadata, Viewport } from "next"; import Providers from "~/components/Providers"; export const viewport: Viewport = { @@ -13,15 +13,16 @@ export const viewport: Viewport = { viewportFit: "cover", }; +export const metadata: Metadata = { + title: "CourseMate (β版)", + description: "同じ授業の人と友達になろう", +}; + export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( - - - CourseMate - {children} diff --git a/web/components/Header.tsx b/web/components/Header.tsx index f66d3714..60aaa9d7 100644 --- a/web/components/Header.tsx +++ b/web/components/Header.tsx @@ -8,7 +8,7 @@ type Props = { }; export default function Header(props: Props) { - const { title, info } = props; + const { title } = props; return (
{title && ( @@ -20,7 +20,6 @@ export default function Header(props: Props) { )} - {title ? (

{title} @@ -28,15 +27,33 @@ export default function Header(props: Props) { ) : ( )} - {info && ( - +
+ +
+

CourseMate は現在ベータ版です。

+ +
+

); } From ca6b4cc6facbf13454f34d584d7ad4b378149f46 Mon Sep 17 00:00:00 2001 From: naka-12 <104970808+naka-12@users.noreply.github.com> Date: Sun, 13 Apr 2025 14:51:21 +0900 Subject: [PATCH 6/8] fix: update lockfile --- bun.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index 1cc4a83f..1998c206 100644 --- a/bun.lock +++ b/bun.lock @@ -430,7 +430,7 @@ "@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="], - "@types/bun": ["@types/bun@1.2.4", "", { "dependencies": { "bun-types": "1.2.4" } }, "sha512-QtuV5OMR8/rdKJs213iwXDpfVvnskPXY/S0ZiFbsTjQZycuqPbMW8Gf/XhLfwE5njW8sxI2WjISURXPlHypMFA=="], + "@types/bun": ["@types/bun@1.2.9", "", { "dependencies": { "bun-types": "1.2.9" } }, "sha512-epShhLGQYc4Bv/aceHbmBhOz1XgUnuTZgcxjxk+WXwNyDXavv5QHD1QEFV0FwbTSQtNq6g4ZcV6y0vZakTjswg=="], "@types/caseless": ["@types/caseless@0.12.5", "", {}, "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="], @@ -536,7 +536,7 @@ "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - "bun-types": ["bun-types@1.2.4", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-nDPymR207ZZEoWD4AavvEaa/KZe/qlrbMSchqpQwovPZCKc7pwMoENjEtHgMKaAjJhy+x6vfqSBA1QU3bJgs0Q=="], + "bun-types": ["bun-types@1.2.9", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-dk/kOEfQbajENN/D6FyiSgOKEuUi9PWfqKQJEgwKrCMWbjS/S6tEXp178mWvWAcUSYm9ArDlWHZKO3T/4cLXiw=="], "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], From e198c4730725203e0b7f486d68e25e12111d0abc Mon Sep 17 00:00:00 2001 From: naka-12 <104970808+naka-12@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:07:05 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=E6=8E=88=E6=A5=AD=E3=81=AE=E7=99=BB?= =?UTF-8?q?=E9=8C=B2=E3=82=82=E8=88=88=E5=91=B3=E5=88=86=E9=87=8E=E3=81=AE?= =?UTF-8?q?=E7=99=BB=E9=8C=B2=E3=82=82=200=20=E4=BB=B6=E3=81=AE=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=81=AF=E9=99=A4=E5=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/prisma/sql/recommend.sql | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/prisma/sql/recommend.sql b/server/prisma/sql/recommend.sql index ad2ad7a4..82e714c7 100644 --- a/server/prisma/sql/recommend.sql +++ b/server/prisma/sql/recommend.sql @@ -26,5 +26,18 @@ AND NOT EXISTS ( AND status = 'PENDING' ) +-- 授業の登録も興味分野の登録も 0 件のユーザは除外 +AND ( + EXISTS ( + SELECT 1 FROM "Enrollment" e + WHERE e."userId" = recv.id + ) + OR + EXISTS ( + SELECT 1 FROM "Interest" i + WHERE i."userId" = recv.id + ) +) + ORDER BY overlap DESC LIMIT $2 OFFSET $3; From c171119c5bdd9a08b7aec5a5db78929fba4fa78d Mon Sep 17 00:00:00 2001 From: naka-12 <104970808+naka-12@users.noreply.github.com> Date: Mon, 14 Apr 2025 01:40:33 +0900 Subject: [PATCH 8/8] =?UTF-8?q?recommend=20=E3=81=A7=E3=83=A6=E3=83=BC?= =?UTF-8?q?=E3=82=B6=E6=83=85=E5=A0=B1=E3=82=92=20JOIN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/prisma/sql/recommend.sql | 38 ++++++++++++++++- .../src/functions/engines/recommendation.ts | 41 ++++++++----------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/server/prisma/sql/recommend.sql b/server/prisma/sql/recommend.sql index 82e714c7..1720f38b 100644 --- a/server/prisma/sql/recommend.sql +++ b/server/prisma/sql/recommend.sql @@ -1,6 +1,33 @@ -- $1 = senderId SELECT - *, + recv.id, + recv.name, + recv.gender, + recv.grade, + recv.faculty, + recv.department, + recv.intro, + recv."guid", + recv."pictureUrl", + json_agg(DISTINCT jsonb_build_object( + 'id', c.id, + 'name', c.name, + 'teacher', c.teacher, + 'slots', ( + SELECT json_agg( + jsonb_build_object( + 'courseId', "Slot"."courseId", + 'day', "Slot"."day", + 'period', "Slot"."period" + ) + ) FROM "Slot" WHERE "Slot"."courseId" = c.id) + ) + ) AS "courses", + json_agg(DISTINCT jsonb_build_object( + 'id', s.id, + 'name', s.name, + 'group', s.group + )) AS "interestSubjects", -- course overlap (SELECT COUNT(1) FROM "Course" course WHERE EXISTS (SELECT 1 FROM "Enrollment" e WHERE e."courseId" = course.id AND e."userId" = recv.id) @@ -12,6 +39,13 @@ SELECT AND EXISTS (SELECT 1 FROM "Interest" i WHERE i."subjectId" = subj.id AND i."userId" = $1) ) AS overlap FROM "User" recv + +INNER JOIN "Enrollment" ON "Enrollment"."userId" = recv.id +INNER JOIN "Course" c on c.id = "Enrollment"."courseId" +INNER JOIN "Slot" ON "Slot"."courseId" = c.id +INNER JOIN "Interest" ON "Interest"."userId" = recv.id +INNER JOIN "InterestSubject" s ON s.id = "Interest"."subjectId" + WHERE recv.id <> $1 AND NOT EXISTS ( @@ -39,5 +73,7 @@ AND ( ) ) +GROUP BY recv.id + ORDER BY overlap DESC LIMIT $2 OFFSET $3; diff --git a/server/src/functions/engines/recommendation.ts b/server/src/functions/engines/recommendation.ts index 64222a0a..bf1f78f6 100644 --- a/server/src/functions/engines/recommendation.ts +++ b/server/src/functions/engines/recommendation.ts @@ -1,9 +1,11 @@ import { recommend } from "@prisma/client/sql"; -import type { UserID, UserWithCoursesAndSubjects } from "common/types"; +import type { + Course, + InterestSubject, + UserID, + UserWithCoursesAndSubjects, +} from "common/types"; import { prisma } from "../../database/client"; -import { getCoursesByUserId } from "../../database/courses"; -import * as interest from "../../database/interest"; -import { getUserByID } from "../../database/users"; export async function recommendedTo( user: UserID, @@ -15,23 +17,16 @@ export async function recommendedTo( count: number; }> > { - const result = await prisma.$queryRawTyped(recommend(user, limit, offset)); - return Promise.all( - result.map(async (res) => { - const { overlap: count, ...u } = res; - if (count === null) throw new Error("count is null: something is wrong"); - // TODO: user の情報はここで再度 DB に問い合わせるのではなく、 recommend の sql で取得 - const user = await getUserByID(u.id); - const courses = getCoursesByUserId(u.id); - const subjects = interest.of(u.id); - return { - count: Number(count), - u: { - ...user, - courses: await courses, - interestSubjects: await subjects, - }, - }; - }), - ); + const users = await prisma.$queryRawTyped(recommend(user, limit, offset)); + return users.map((user) => { + const { overlap: count, ...u } = user; + return { + count: Number(count), + u: { + ...u, + interestSubjects: u.interestSubjects as InterestSubject[], // TODO: type + courses: u.courses as Course[], // TODO: type + }, + }; + }); }