From 2e819f8ef8efabd25415fd01eea87d52ade12635 Mon Sep 17 00:00:00 2001 From: Yone Date: Tue, 18 Feb 2025 17:40:20 +0900 Subject: [PATCH 01/21] =?UTF-8?q?=E3=81=84=E3=82=89=E3=81=AA=E3=81=84?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/lib/gemini.ts | 86 --------------------------------------- 1 file changed, 86 deletions(-) diff --git a/backend/src/lib/gemini.ts b/backend/src/lib/gemini.ts index 6c29fa6..46f02a8 100644 --- a/backend/src/lib/gemini.ts +++ b/backend/src/lib/gemini.ts @@ -139,90 +139,4 @@ const generateTanka = async (originalText: string): Promise => { } }; -/* -const getGeminiText = async (c: Context) => { - try { - // POSTメソッド以外は拒否 - if (c.req.method !== 'POST') { - return c.json( - { - success: 'false', - message: { - status: 405, - message: 'Bad Request', - description: 'POSTメソッドでリクエストしてください。', - }, - }, - 405 - ); - } - - // リクエストボディから prompt を取得 - const { prompt } = await c.req.json(); - if (!prompt) { - return c.json({ error: 'Prompt is required' }, 400); - } - - const apiKey = env.GEMINI_API_KEY; - if (!apiKey) { - throw new Error('APIが設定されていません。'); - } - - const genAI = new GoogleGenerativeAI(apiKey); - const model = genAI.getGenerativeModel({ - model: 'gemini-2.0-pro-exp-02-05', - systemInstruction: `SNSの投稿を短歌にしてください。原文の特徴的な要素はそのままに、比喩表現を使った趣深い短歌にしてください。出力の形式は以下のJSONスキーマに従ってください。各値は日本語で出力してください。 -{ - "type": "object", - "description": "変換した短歌", - "properties": { - "response": { - "type": "array", - "description": "ユーザーアカウント作成のレスポンスデータの配列", - "items": { - "type": "object", - "properties": { - "line1": { - "type": "string", - "description": "短歌の1行目" - }, - "line2": { - "type": "string", - "description": "短歌の2行目" - }, - "line3": { - "type": "string", - "description": "短歌の3行目" - }, - "line4": { - "type": "string", - "description": "短歌の4行目" - }, - "line5": { - "type": "string", - "description": "短歌の5行目" - } - }, - "required": ["line1", "line2", "line3", "line4", "line5"] - } - }, - "required": ["response"] - } -}`, - generationConfig: { responseMimeType: 'application/json' }, - }); - - const result = await model.generateContent(prompt); - const jsonResponse = JSON.parse(result.response.text()); - console.log(jsonResponse); - console.log('-----------------------------'); - - return c.json(jsonResponse); - } catch (error) { - console.error('APIエラー:', error); - return c.json({ error: 'Internal Server Error' }, 500); - } -}; -*/ - export default generateTanka; From 7aea367cbf36727411fe5322915146537614f87b Mon Sep 17 00:00:00 2001 From: RAIT-09 Date: Wed, 19 Feb 2025 14:58:26 +0900 Subject: [PATCH 02/21] =?UTF-8?q?app=E3=81=AEpage.tsx=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/page.tsx | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 frontend/src/app/page.tsx diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx deleted file mode 100644 index 86ca7dc..0000000 --- a/frontend/src/app/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Home() { - return ( -
-

Tankalizer

-
- ); -} From ecb6056b097377f3aa15f66a27685787b103f824 Mon Sep 17 00:00:00 2001 From: RAIT-09 Date: Wed, 19 Feb 2025 15:16:23 +0900 Subject: [PATCH 03/21] =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=A0=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=92app=E7=9B=B4=E4=B8=8B=E3=81=AB?= =?UTF-8?q?=E7=A7=BB=E8=A1=8C=EF=BC=8CYomu=E3=81=AE=E3=83=AA=E3=83=80?= =?UTF-8?q?=E3=82=A4=E3=83=AC=E3=82=AF=E3=83=88=E5=85=88=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/{timeline => }/page.tsx | 0 frontend/src/app/yomu/AfterYomu.tsx | 2 +- frontend/src/app/yomu/page.tsx | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename frontend/src/app/{timeline => }/page.tsx (100%) diff --git a/frontend/src/app/timeline/page.tsx b/frontend/src/app/page.tsx similarity index 100% rename from frontend/src/app/timeline/page.tsx rename to frontend/src/app/page.tsx diff --git a/frontend/src/app/yomu/AfterYomu.tsx b/frontend/src/app/yomu/AfterYomu.tsx index b5f977d..f990c0f 100644 --- a/frontend/src/app/yomu/AfterYomu.tsx +++ b/frontend/src/app/yomu/AfterYomu.tsx @@ -193,7 +193,7 @@ const AfterYomu = ({ tanka, imagePath, userName, userIconPath }: AfterYomuProps) ); }; From 11ddb354463190bd40d4d2fe047e4455e2ec22ac Mon Sep 17 00:00:00 2001 From: RAIT-09 Date: Wed, 19 Feb 2025 21:09:46 +0900 Subject: [PATCH 10/21] =?UTF-8?q?=E6=97=A5=E4=BB=98=E3=81=AE=E4=B8=8B?= =?UTF-8?q?=E3=81=AB=E6=99=82=E9=96=93=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/timeline/utils/kanjiNumber.tsx | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/timeline/utils/kanjiNumber.tsx b/frontend/src/app/timeline/utils/kanjiNumber.tsx index e7341dc..8aa3dff 100644 --- a/frontend/src/app/timeline/utils/kanjiNumber.tsx +++ b/frontend/src/app/timeline/utils/kanjiNumber.tsx @@ -83,15 +83,26 @@ export const formatDateKanji = (date: Date): ReactNode => { const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); + const hour = date.getHours(); + const minute = date.getMinutes(); return ( -

- {`${toKanjiNumberSimply(year)}`} - - {`${toKanjiNumber(month)}`} - - {`${toKanjiNumber(day)}`} - -

+
+

+ 令和 + {`${toKanjiNumberSimply(year - 2018)}`} + + {`${toKanjiNumber(month)}`} + + {`${toKanjiNumber(day)}`} + +

+

+ {`${toKanjiNumber(hour)}`} + + {`${toKanjiNumber(minute)}`} + +

+
); }; From db84424cb1b47ec50b6a4b78acd5ef439e4f44ea Mon Sep 17 00:00:00 2001 From: RAIT-09 Date: Wed, 19 Feb 2025 21:11:49 +0900 Subject: [PATCH 11/21] =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=A0=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=81=AE=E4=B8=80=E7=95=AA=E4=B8=8A=E3=81=BE?= =?UTF-8?q?=E3=81=A7=E6=88=BB=E3=82=8B=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Timeline.tsx | 36 ++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Timeline.tsx b/frontend/src/components/Timeline.tsx index af87f6a..8b0220e 100644 --- a/frontend/src/components/Timeline.tsx +++ b/frontend/src/components/Timeline.tsx @@ -1,11 +1,13 @@ 'use client'; -import React from 'react'; +import React, { useEffect } from 'react'; import { useState, useRef, useCallback } from 'react'; import { PostTypes } from '@/types/postTypes'; import PostList from '@/components/PostList'; import fetchPosts from '@/app/timeline/actions/fetchPosts'; import { useSession } from 'next-auth/react'; +import { FaArrowUp } from 'react-icons/fa'; +import { motion } from 'framer-motion'; // props の型定義 interface TimelineProps { @@ -30,11 +32,12 @@ const Timeline = ({ limit, max, targetUserUrl, className }: TimelineProps) => { const [hasMore, setHasMore] = useState(true); // セッションの取得 const session = useSession(); - //IntersectionObserverを保持するためのref const observer = useRef(null); // 投稿取得の重複実行を防ぐためのref const isFetchingRef = useRef(false); + // 一番上まで戻るボタンの表示状態 + const [showTopButton, setShowTopButton] = useState(false); /** * 追加の投稿データを取得し,状態を更新する非同期関数のCallback Ref @@ -103,12 +106,41 @@ const Timeline = ({ limit, max, targetUserUrl, className }: TimelineProps) => { setPosts((prevPosts) => prevPosts.filter((post) => post.id !== postId)); }; + // スクロールを監視するためのイベントリスナーの追加 + useEffect(() => { + const handleScroll = () => { + if (window.scrollY > window.innerHeight) { + setShowTopButton(true); + } else { + setShowTopButton(false); + } + }; + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + return (
{hasMore &&

投稿を取得中...

}
{!hasMore &&

これ以上投稿を取得できません。

} + {showTopButton && ( + { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }} + className='fixed left-1/2 top-12 my-5 flex items-center justify-center rounded-xl bg-orange-400 px-3' + > + + 最新の短歌に戻る + + )}
); }; From 0170e3ad628585ff59ba9a213754311fb39eeba2 Mon Sep 17 00:00:00 2001 From: natanata25 <136555690+natanata25@users.noreply.github.com> Date: Wed, 19 Feb 2025 21:41:23 +0900 Subject: [PATCH 12/21] =?UTF-8?q?Profile=E3=81=AE=E4=B8=8A=E9=83=A8?= =?UTF-8?q?=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/profile/page.tsx | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 frontend/src/app/profile/page.tsx diff --git a/frontend/src/app/profile/page.tsx b/frontend/src/app/profile/page.tsx new file mode 100644 index 0000000..c5a7aa0 --- /dev/null +++ b/frontend/src/app/profile/page.tsx @@ -0,0 +1,48 @@ +'use client'; +import Image from 'next/image'; +import { signIn, signOut, useSession } from 'next-auth/react'; +import React from 'react'; + +const ProfileSettings = () => { + const session = useSession(); + const totalLikes = 120; // 仮のデータ + const totalPosts = 35; // 仮のデータ + + return ( +
+ {session.status === 'authenticated' ? ( +
+
+ プロフィール +
+
+
+ {session.data.user?.image && ( + プロフィール画像 + )} +
+ +
+

総雅数: {totalLikes}

+

総投稿数: {totalPosts}

+
+
+
+
+
+ ) : ( +
ログインしてください。
+ )} +
+ ); +}; + +export default ProfileSettings; From afec2abc930793ec37ba4b884f8f6f313801dda6 Mon Sep 17 00:00:00 2001 From: RAIT-09 Date: Wed, 19 Feb 2025 21:42:22 +0900 Subject: [PATCH 13/21] =?UTF-8?q?=E3=82=A2=E3=83=8B=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=82=B7=E3=83=A7=E3=83=B3=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/page.tsx | 18 +++++++++++++++--- frontend/src/components/DropDownButton.tsx | 10 ++++++++-- frontend/src/components/Timeline.tsx | 3 +-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 53ac091..999ed9b 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -10,6 +10,7 @@ import { useSession } from 'next-auth/react'; import LoginDialog from '@/components/LoginDialog'; import { useRouter } from 'next/navigation'; import Timeline from '@/components/Timeline'; +import { motion } from 'framer-motion'; const LIMIT = 10; // 一度に取得する投稿数 const MAX = 100; // タイムラインに表示できる最大投稿数 @@ -67,10 +68,21 @@ const Page = () => { {/* ハンバーガーメニュー */} {isMenuOpen && (
-
+ -
-
setIsMenuOpen(false)} className='size-full bg-black/50'>
+ + setIsMenuOpen(false)} + className='size-full bg-black/50' + />
)} diff --git a/frontend/src/components/DropDownButton.tsx b/frontend/src/components/DropDownButton.tsx index 1706e53..f77e30e 100644 --- a/frontend/src/components/DropDownButton.tsx +++ b/frontend/src/components/DropDownButton.tsx @@ -3,6 +3,7 @@ import { ReactNode, useEffect, useRef, useState } from 'react'; import { BsThreeDots } from 'react-icons/bs'; +import { motion } from 'framer-motion'; // 各項目の型定義 export interface DropDownItem { @@ -58,7 +59,12 @@ const DropDownButton = ({ className, items }: DropDownButtonProps) => { {isOpen && ( -
    + {items.map((item) => (
  • {
  • ))} -
+ )}
); diff --git a/frontend/src/components/Timeline.tsx b/frontend/src/components/Timeline.tsx index 8b0220e..0d944f4 100644 --- a/frontend/src/components/Timeline.tsx +++ b/frontend/src/components/Timeline.tsx @@ -131,11 +131,10 @@ const Timeline = ({ limit, max, targetUserUrl, className }: TimelineProps) => { initial={{ opacity: 0, x: '-50%', y: -10 }} animate={{ opacity: 1, x: '-50%', y: 0 }} transition={{ duration: 0.2 }} - whileHover={{ scale: 1.1 }} onClick={() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }} - className='fixed left-1/2 top-12 my-5 flex items-center justify-center rounded-xl bg-orange-400 px-3' + className='fixed left-1/2 top-12 my-5 flex items-center justify-center rounded-xl bg-orange-400 px-3 hover:bg-orange-500' > 最新の短歌に戻る From 3e8163d949d106d43673d4f1add9b111c7370c6d Mon Sep 17 00:00:00 2001 From: ABfry Date: Wed, 19 Feb 2025 22:13:21 +0900 Subject: [PATCH 14/21] infra --- Makefile | 38 ++++++++++++++++++++++++++++++++++++++ infra/.gitignore | 1 + 2 files changed, 39 insertions(+) create mode 100644 infra/.gitignore diff --git a/Makefile b/Makefile index 740b2a3..656f51c 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# 開発用 front: cd frontend && npm run dev @@ -19,3 +20,40 @@ down: sb: cd frontend && npm run storybook + + +# ECR + + +# ECR URLの定義 +FRONT_ECR_URL := $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com/$(FRONT_IMAGE_NAME) +BACK_ECR_URL := $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com/$(BACK_IMAGE_NAME) +UUID := $(shell uuidgen) + +login-ecr: + aws ecr get-login-password --region $(AWS_REGION) | docker login --username AWS --password-stdin $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com + +build-ecr-front: + docker build --platform linux/amd64 -t $(FRONT_IMAGE_NAME) -f ./frontend/Dockerfile ./frontend + +build-ecr-back: + docker build --platform linux/amd64 -t $(BACK_IMAGE_NAME) -f ./backend/Dockerfile ./backend + +tag-ecr: build-ecr-front build-ecr-back + docker tag $(FRONT_IMAGE_NAME):$(TAG) $(FRONT_ECR_URL):$(TAG) + docker tag $(BACK_IMAGE_NAME):$(TAG) $(BACK_ECR_URL):$(TAG) + +push-ecr: tag-ecr + docker push $(FRONT_ECR_URL):$(TAG) + docker push $(BACK_ECR_URL):$(TAG) + +tag-ecr-uuid: build-ecr-front build-ecr-back + docker tag $(FRONT_IMAGE_NAME):$(TAG) $(FRONT_ECR_URL):$(UUID) + docker tag $(BACK_IMAGE_NAME):$(TAG) $(BACK_ECR_URL):$(UUID) + +push-ecr-uuid: tag-ecr-uuid + docker push $(FRONT_ECR_URL):$(UUID) + docker push $(BACK_ECR_URL):$(UUID) + +ecr: login-ecr build-ecr-front build-ecr-back tag-ecr tag-ecr-uuid push-ecr push-ecr-uuid + diff --git a/infra/.gitignore b/infra/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/infra/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file From d0e3478df5edaa40c5ea7b89c5c026197993e183 Mon Sep 17 00:00:00 2001 From: ABfry Date: Wed, 19 Feb 2025 22:22:33 +0900 Subject: [PATCH 15/21] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A2=E3=82=A6=E3=83=88=E8=BF=BD=E5=8A=A0=E3=80=81=E7=B4=B0?= =?UTF-8?q?=E3=81=8B=E3=81=84=E3=83=97=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88?= =?UTF-8?q?=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/lib/gemini.ts | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/backend/src/lib/gemini.ts b/backend/src/lib/gemini.ts index ed200cf..fce51b9 100644 --- a/backend/src/lib/gemini.ts +++ b/backend/src/lib/gemini.ts @@ -48,32 +48,27 @@ const generateTanka = async (originalText: string): Promise => { }, yomi0: { type: SchemaType.STRING, - description: - '短歌の1句目のふりがな(基本的に日本語のひらがなだが、短歌にアルファベット部分があった場合はその部分のみアルファベットで出力)', + description: '短歌の1句目のふりがな', nullable: false, }, yomi1: { type: SchemaType.STRING, - description: - '短歌の2句目のふりがな(基本的に日本語のひらがなだが、短歌にアルファベット部分があった場合はその部分のみアルファベットで出力)', + description: '短歌の2句目のふりがな', nullable: false, }, yomi2: { type: SchemaType.STRING, - description: - '短歌の3句目のふりがな(基本的に日本語のひらがなだが、短歌にアルファベット部分があった場合はその部分のみアルファベットで出力)', + description: '短歌の3句目のふりがな', nullable: false, }, yomi3: { type: SchemaType.STRING, - description: - '短歌の4句目のふりがな(基本的に日本語のひらがなだが、短歌にアルファベット部分があった場合はその部分のみアルファベットで出力)', + description: '短歌の4句目のふりがな', nullable: false, }, yomi4: { type: SchemaType.STRING, - description: - '短歌の5句目のふりがな(基本的に日本語のひらがなだが、短歌にアルファベット部分があった場合はその部分のみアルファベットで出力)', + description: '短歌の5句目のふりがな', nullable: false, }, }, @@ -110,12 +105,12 @@ const generateTanka = async (originalText: string): Promise => { // アルファベット(全角、半角)、ひらがな、カタカナ、漢字を1文字としてカウント const regex = /[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/g; const matchedChars = line.match(regex) || []; - console.log(matchedChars); + // console.log(matchedChars); // 「ゃ」「ャ」「ゅ」「ュ」「ょ」「ョ」はカウントしない const excludeChars = ['ゃ', 'ャ', 'ゅ', 'ュ', 'ょ', 'ョ']; const validChars = matchedChars.filter((char) => !excludeChars.includes(char)); const count = validChars.length; - console.log('count: ', count); + // console.log('count: ', count); // 文字数をカウント(アルファベット(全角、半角)、ひらがな、カタカナ、漢字を1文字としてカウント) return Math.abs(count - expectedCharaCount[index]) <= 1; // 1文字分までの誤差は許容 @@ -133,7 +128,7 @@ const generateTanka = async (originalText: string): Promise => { const result = await model.generateContent(originalText); - console.log(result.response.text()); + // console.log(result.response.text()); const jsonResponse = JSON.parse(result.response.text()); From 321807ed63f0bca6f2205658c2f537ebb9b492e1 Mon Sep 17 00:00:00 2001 From: Yone Date: Wed, 19 Feb 2025 22:25:57 +0900 Subject: [PATCH 16/21] =?UTF-8?q?printLine()=E3=82=92=E8=AA=AD=E3=81=BF?= =?UTF-8?q?=E3=82=84=E3=81=99=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/lib/gemini.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/src/lib/gemini.ts b/backend/src/lib/gemini.ts index ed200cf..99b4a98 100644 --- a/backend/src/lib/gemini.ts +++ b/backend/src/lib/gemini.ts @@ -2,6 +2,10 @@ import type { Context } from 'hono'; import { env } from '../config/env.js'; import { GoogleGenerativeAI, SchemaType } from '@google/generative-ai'; +const printLine = (): void => { + console.log('--------------------------------'); +}; + const generateTanka = async (originalText: string): Promise => { // Geminiで短歌生成 @@ -122,10 +126,6 @@ const generateTanka = async (originalText: string): Promise => { }); }; - const printLine = (): void => { - console.log('--------------------------------'); - }; - // 生成後、型のチェック(3回まで) for (let i = 0; i < 3; i++) { printLine(); @@ -179,4 +179,16 @@ const generateTanka = async (originalText: string): Promise => { } }; +const getNews = async (originalText: string): Promise => { + try { + const apiKey = env.GEMINI_API_KEY; + if (!apiKey) { + throw new Error('APIが設定されていません。'); + } + } catch (error) { + console.error('APIエラー:', error); + return {}; + } +}; + export default generateTanka; From d6a7d7cdd74fc71abfe1461faa3bd14929abeb2b Mon Sep 17 00:00:00 2001 From: Yone Date: Wed, 19 Feb 2025 22:59:00 +0900 Subject: [PATCH 17/21] =?UTF-8?q?=E7=92=B0=E5=A2=83=E5=A4=89=E6=95=B0?= =?UTF-8?q?=E3=81=AE=E8=A8=AD=E5=AE=9A=20TZ=3DAsia/Tokyo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index ffcdf3a..747bb24 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,6 +14,7 @@ services: env_file: - ./frontend/.env environment: + - TZ=Asia/Tokyo - BACKEND_URL=http://backend:8080 backend: build: @@ -27,3 +28,5 @@ services: - /app/node_modules env_file: - ./backend/.env + environment: + - TZ=Asia/Tokyo From af1acc4237f5474147b83f3be63ee87ad7b475dd Mon Sep 17 00:00:00 2001 From: ABfry Date: Wed, 19 Feb 2025 23:11:15 +0900 Subject: [PATCH 18/21] =?UTF-8?q?=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0?= =?UTF-8?q?=E3=83=AD=E3=82=B0=E3=82=A4=E3=83=B3=E3=83=9A=E3=83=BC=E3=82=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.env.exapmle | 3 ++- frontend/src/app/login/page.tsx | 34 +++++++++++++++++++++++++++++++++ frontend/src/auth/config.ts | 31 ++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 frontend/src/app/login/page.tsx diff --git a/frontend/.env.exapmle b/frontend/.env.exapmle index 59450db..5257ca2 100644 --- a/frontend/.env.exapmle +++ b/frontend/.env.exapmle @@ -1,4 +1,5 @@ NEXT_PUBLIC_ADOBE_FONTS_KIT_ID= AUTH_SECRET= GITHUB_CLIENT_ID= -GITHUB_CLIENT_SECREAT= \ No newline at end of file +GITHUB_CLIENT_SECREAT= +AUTH_URL= \ No newline at end of file diff --git a/frontend/src/app/login/page.tsx b/frontend/src/app/login/page.tsx new file mode 100644 index 0000000..2553031 --- /dev/null +++ b/frontend/src/app/login/page.tsx @@ -0,0 +1,34 @@ +import { redirect } from 'next/navigation'; +import { signIn, providerMap } from '@/auth/config'; +import { AuthError } from 'next-auth'; + +export default async function SignInPage(props: { + searchParams: { callbackUrl: string | undefined }; +}) { + return ( +
+ {Object.values(providerMap).map((provider) => ( +
{ + 'use server'; + try { + await signIn(provider.id, { + redirectTo: props.searchParams?.callbackUrl ?? '', + }); + } catch (error) { + if (error instanceof AuthError) { + return redirect(`${process.env.AUTH_URL}?error=${error.type}`); + } + throw error; + } + }} + > + +
+ ))} +
+ ); +} diff --git a/frontend/src/auth/config.ts b/frontend/src/auth/config.ts index c919975..080ec61 100644 --- a/frontend/src/auth/config.ts +++ b/frontend/src/auth/config.ts @@ -1,13 +1,28 @@ import NextAuth from 'next-auth'; -import Credentials from 'next-auth/providers/credentials'; import GitHub from 'next-auth/providers/github'; -import Google from 'next-auth/providers/google'; +import type { Provider } from 'next-auth/providers'; + +const providers: Provider[] = [ + GitHub({ + clientId: process.env.GITHUB_CLIENT_ID, + clientSecret: process.env.GITHUB_CLIENT_SECREAT, + }), +]; + +export const providerMap = providers + .map((provider) => { + if (typeof provider === 'function') { + const providerData = provider(); + return { id: providerData.id, name: providerData.name }; + } else { + return { id: provider.id, name: provider.name }; + } + }) + .filter((provider) => provider.id !== 'credentials'); export const { auth, handlers, signIn, signOut } = NextAuth({ - providers: [ - GitHub({ - clientId: process.env.GITHUB_CLIENT_ID, - clientSecret: process.env.GITHUB_CLIENT_SECREAT, - }), - ], + providers, + pages: { + signIn: '/login', + }, }); From 5817b51e85d9c69dc9e1aabf898ec1864577a7d4 Mon Sep 17 00:00:00 2001 From: ABfry Date: Wed, 19 Feb 2025 23:14:29 +0900 Subject: [PATCH 19/21] fix dynamic api --- frontend/src/app/login/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/login/page.tsx b/frontend/src/app/login/page.tsx index 2553031..28c8547 100644 --- a/frontend/src/app/login/page.tsx +++ b/frontend/src/app/login/page.tsx @@ -3,7 +3,7 @@ import { signIn, providerMap } from '@/auth/config'; import { AuthError } from 'next-auth'; export default async function SignInPage(props: { - searchParams: { callbackUrl: string | undefined }; + searchParams: Promise<{ callbackUrl: string | undefined }>; }) { return (
@@ -14,7 +14,7 @@ export default async function SignInPage(props: { 'use server'; try { await signIn(provider.id, { - redirectTo: props.searchParams?.callbackUrl ?? '', + redirectTo: (await props.searchParams)?.callbackUrl ?? '', }); } catch (error) { if (error instanceof AuthError) { From 74c7fa62696677b122bb6d62a975bf4485eb29e7 Mon Sep 17 00:00:00 2001 From: natanata25 <136555690+natanata25@users.noreply.github.com> Date: Wed, 19 Feb 2025 23:17:05 +0900 Subject: [PATCH 20/21] =?UTF-8?q?profil=E7=94=BB=E9=9D=A2=E3=81=AE?= =?UTF-8?q?=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/profile/page.tsx | 56 +++++++++++++++++++------------ 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/frontend/src/app/profile/page.tsx b/frontend/src/app/profile/page.tsx index c5a7aa0..aee13d4 100644 --- a/frontend/src/app/profile/page.tsx +++ b/frontend/src/app/profile/page.tsx @@ -2,6 +2,7 @@ import Image from 'next/image'; import { signIn, signOut, useSession } from 'next-auth/react'; import React from 'react'; +import Timeline from '@/components/Timeline'; const ProfileSettings = () => { const session = useSession(); @@ -10,33 +11,44 @@ const ProfileSettings = () => { return (
+ {/* ヘッダ */} +
+
Tankalizer
+
+
+ Background +
+ {session.status === 'authenticated' ? ( -
-
- プロフィール -
-
-
- {session.data.user?.image && ( - プロフィール画像 - )} -
- -
-

総雅数: {totalLikes}

-

総投稿数: {totalPosts}

+
+
+
+ プロフィール +
+
+
+ {session.data.user?.image && ( + プロフィール画像 + )} +
+ +
+

総雅数: {totalLikes}

+

総投稿数: {totalPosts}

+
+
) : (
ログインしてください。
From 5c8ba0af46449bd19dc147473e1708087c099c7a Mon Sep 17 00:00:00 2001 From: natanata25 <136555690+natanata25@users.noreply.github.com> Date: Wed, 19 Feb 2025 23:30:24 +0900 Subject: [PATCH 21/21] =?UTF-8?q?=E8=87=AA=E5=88=86=E3=81=AE=E3=82=BF?= =?UTF-8?q?=E3=82=A4=E3=83=A0=E3=83=A9=E3=82=A4=E3=83=B3=E3=81=AE=E3=81=BF?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/profile/page.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/profile/page.tsx b/frontend/src/app/profile/page.tsx index aee13d4..5ae209a 100644 --- a/frontend/src/app/profile/page.tsx +++ b/frontend/src/app/profile/page.tsx @@ -15,7 +15,8 @@ const ProfileSettings = () => {
Tankalizer
-
+ +
Background
@@ -48,7 +49,7 @@ const ProfileSettings = () => {
- +
) : (
ログインしてください。