Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #70

Merged
merged 55 commits into from
Feb 18, 2025
Merged
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
e8d6122
プロンプト変更
yone-al Feb 16, 2025
455ac55
整列
ABfry Feb 17, 2025
9796750
投稿ボタン、文字数制限外のときの警告表示
ABfry Feb 17, 2025
3d4ec64
Merge branch 'hayato/develop' into hayato/feature/post-front
ABfry Feb 17, 2025
aa29c4b
"yomu"辞書登録
ABfry Feb 17, 2025
ae94cde
auth系env追加
ABfry Feb 17, 2025
781fdc8
短歌API連携
ABfry Feb 17, 2025
255a8f8
import framer-motion
ABfry Feb 17, 2025
352eaa6
Loading compnent
ABfry Feb 17, 2025
b8a43ff
createPost APIの不具合修正
TARO-gh Feb 17, 2025
3a630cf
投稿ステート管理、お気持ち程度のレスポンシブ
ABfry Feb 17, 2025
1f6a1aa
getPost APIの不具合修正
TARO-gh Feb 17, 2025
f373ca6
タイムラインへの認証の統合
RAIT-09 Feb 17, 2025
adbd391
生成した短歌が不正な形式な場合は3回まで再生成
yone-al Feb 17, 2025
6ae41a8
Merge remote-tracking branch 'origin/develop' into RAIT-09/develop
RAIT-09 Feb 17, 2025
3a6b05a
全角アルファベット対応
yone-al Feb 17, 2025
15110f0
Merge branch 'develop' into yone/develop
yone-al Feb 17, 2025
bbbf0f9
Merge pull request #57 from kc3hack/RAIT-09/develop
RAIT-09 Feb 17, 2025
af9f39a
Merge remote-tracking branch 'origin/develop' into taro/develop
TARO-gh Feb 17, 2025
c2e2424
短歌の形式を配列に変更
RAIT-09 Feb 17, 2025
a412166
gemini-2.0-flashにモデル変更
ABfry Feb 17, 2025
085f87e
短歌の形式を配列に変更
RAIT-09 Feb 17, 2025
93cf56c
tankaが空の場合の対応
TARO-gh Feb 17, 2025
471f822
読み仮名で文字数カウントするよう変更
ABfry Feb 17, 2025
e702752
短歌誤差1文字に変更
ABfry Feb 17, 2025
d5e7975
Merge pull request #58 from kc3hack/yone/develop
ABfry Feb 17, 2025
f4daf03
投稿画面ステート
ABfry Feb 17, 2025
747fa6e
Merge branch 'hayato/develop' into hayato/feature/post-front
ABfry Feb 17, 2025
2b6da7f
api送信周り修正
ABfry Feb 17, 2025
4f2db3b
画像アップロードボタン
ABfry Feb 17, 2025
80f616e
getPostの修正
TARO-gh Feb 17, 2025
42e018f
コメントアウト追加、最大画像サイズ定義
ABfry Feb 18, 2025
80451fe
Merge remote-tracking branch 'origin/develop' into RAIT-09/develop
RAIT-09 Feb 18, 2025
9e32c21
Merge remote-tracking branch 'origin/develop' into taro/develop
TARO-gh Feb 18, 2025
b254201
Merge pull request #59 from kc3hack/taro/develop
TARO-gh Feb 18, 2025
7f01496
getPost APIの修正
TARO-gh Feb 18, 2025
163e7d3
Merge pull request #63 from kc3hack/taro/develop
TARO-gh Feb 18, 2025
30e9ba7
GifButtonのバグ修正
RAIT-09 Feb 18, 2025
c7ffe49
Merge remote-tracking branch 'origin/develop' into RAIT-09/develop
RAIT-09 Feb 18, 2025
6c2af4f
短歌アニメーション
ABfry Feb 18, 2025
f9cd879
Merge pull request #64 from kc3hack/hayato/feature/post-front
ABfry Feb 18, 2025
793f95e
Merge pull request #65 from kc3hack/hayato/develop
ABfry Feb 18, 2025
38eb2b6
タイムラインからAPI叩いて投稿取得
RAIT-09 Feb 18, 2025
36e50bb
Merge remote-tracking branch 'origin/develop' into RAIT-09/develop
RAIT-09 Feb 18, 2025
961184b
画像がアップロードされなかった際エラーになる問題修正
ABfry Feb 18, 2025
74567aa
投稿失敗時エラー処理
ABfry Feb 18, 2025
5fc1c20
Merge pull request #66 from kc3hack/hayato/feature/post-front
ABfry Feb 18, 2025
008293c
Merge pull request #67 from kc3hack/hayato/develop
ABfry Feb 18, 2025
34471e8
localhostからbackendに変更
RAIT-09 Feb 18, 2025
1461b94
dockerとlocalでバックエンドURLの切り替え
ABfry Feb 18, 2025
236295c
Merge pull request #68 from kc3hack/hayato/develop
ABfry Feb 18, 2025
9d85661
Merge remote-tracking branch 'origin/develop' into RAIT-09/develop
RAIT-09 Feb 18, 2025
a0e11c1
DockerとlocalでfetchPostsのURL変更
RAIT-09 Feb 18, 2025
1082266
ッをツにraplace
ABfry Feb 18, 2025
54134f9
Merge pull request #69 from kc3hack/RAIT-09/develop
RAIT-09 Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
タイムラインへの認証の統合
RAIT-09 committed Feb 17, 2025
commit f373ca6c60604ee0bfded45baa47baf68cfdd61b
33 changes: 24 additions & 9 deletions frontend/src/app/timeline/page.tsx
Original file line number Diff line number Diff line change
@@ -9,6 +9,9 @@ import FloatingActionButton from '@/components/FloatingActionButton';
import { MdOutlineMenu } from 'react-icons/md';
import SideMenu from '@/components/SideMenu';
import Image from 'next/image';
import { useSession } from 'next-auth/react';
import LoginDialog from '@/components/LoginDialog';
import { useRouter } from 'next/navigation';

const LIMIT = 10;

@@ -21,10 +24,15 @@ const Timeline = () => {
const [isLoading, setIsLoading] = useState(false);
// これ以上取得できる投稿があるかのフラグ
const [hasMore, setHasMore] = useState(true);
// ログインしているユーザを保持するState
const [user] = useState({ name: 'Name', bio: 'bio', iconUrl: '/iconDefault.png' });
// ハンバーガーメニューの開閉状態
const [isMenuOpen, setIsMenuOpen] = useState(false);
// セッションの取得
const session = useSession();
// ログイン状態
const isLoggedIn = session.status === 'authenticated';
// ログイン促進ダイアログの開閉状態
const [loginDialogOpen, setLoginDialogOpen] = useState(false);
const router = useRouter();

//IntersectionObserverを保持するためのref
const observer = useRef<IntersectionObserver | null>(null);
@@ -104,11 +112,7 @@ const Timeline = () => {
{/* タイムライン */}
<div className='pt-12'>
<div className='relative mx-auto max-w-lg'>
<SideMenu
user={user}
className='absolute top-5 hidden lg:block'
style={{ left: '-12rem' }}
/>
<SideMenu className='absolute top-5 hidden lg:block' style={{ left: '-12rem' }} />
<PostList posts={posts} className='mx-auto max-w-sm lg:max-w-lg' />
{isLoading && <p className='py-3 text-center'>投稿を取得中...</p>}
<div ref={targetRef} className='h-px' />
@@ -117,17 +121,28 @@ const Timeline = () => {
</div>

{/* 投稿(詠)ボタン */}
<FloatingActionButton />
<FloatingActionButton
onClick={() => {
if (isLoggedIn) {
router.push('/yomu');
} else {
setLoginDialogOpen(true);
}
}}
/>

{/* ハンバーガーメニュー */}
{isMenuOpen && (
<div className='fixed inset-0 z-50 justify-center lg:hidden'>
<div className='flex h-fit w-full bg-white py-4'>
<SideMenu user={user} className='mx-auto' />
<SideMenu className='mx-auto' />
</div>
<div onClick={() => setIsMenuOpen(false)} className='size-full bg-black/50'></div>
</div>
)}

{/* ログイン確認ダイアログ表示が有効の場合,ダイアログを表示する */}
{loginDialogOpen && <LoginDialog isOpen={loginDialogOpen} setIsOpen={setLoginDialogOpen} />}
</div>
);
};
6 changes: 5 additions & 1 deletion frontend/src/components/DropDownButton.tsx
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ interface DropDownButtonProps {
const DropDownButton = ({ className, items }: DropDownButtonProps) => {
const [isOpen, setIsOpen] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const hasItem = items.length > 0;

useEffect(() => {
if (!isOpen) return;
@@ -46,7 +47,10 @@ const DropDownButton = ({ className, items }: DropDownButtonProps) => {
};

return (
<div className={`${className} relative inline-block`} ref={containerRef}>
<div
className={`${className} relative inline-block ${hasItem ? '' : 'hidden'}`}
ref={containerRef}
>
<button
className='mx-auto flex size-7 items-center justify-center rounded-full bg-transparent hover:bg-black/5'
onClick={() => toggleDropDown()}
37 changes: 37 additions & 0 deletions frontend/src/components/LoginDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// クライアントコンポーネント
'use client';

import { signIn } from 'next-auth/react';
import Dialog from './Dialog';

// props の型定義
interface LoginDialogProps {
isOpen: boolean;
setIsOpen: (open: boolean) => void;
}

/**
* ログインを促すDialogを表示するコンポーネント
* @component LoginDialog
* @return {JSX.Element} LoginDialogを表示するReactコンポーネント
*/
const LoginDialog = ({ isOpen, setIsOpen }: LoginDialogProps) => {
return (
<Dialog
isOpen={isOpen}
title='ログインが必要です'
description='この機能を利用するには,ログインする必要があります.'
yesCallback={() => {
setIsOpen(false);
signIn();
}}
noCallback={() => {
setIsOpen(false);
}}
yesText='ログイン'
noText='今はしない'
/>
);
};

export default LoginDialog;
52 changes: 38 additions & 14 deletions frontend/src/components/Post.tsx
Original file line number Diff line number Diff line change
@@ -11,7 +11,9 @@ import MiyabiButton from '@/components/MiyabiButton';
import DropDownButton from './DropDownButton';
import { formatDateKanji } from '@/app/timeline/utils/kanjiNumber';
import { MdDeleteForever } from 'react-icons/md';
import Dialog from './Dialog';
import { useSession } from 'next-auth/react';
import Dialog from '@/components/Dialog';
import LoginDialog from './LoginDialog';

// props の型定義
interface PostProps {
@@ -34,6 +36,28 @@ const Post = ({ post, className }: PostProps) => {
const [modalOpen, setModalOpen] = useState(false);
// 削除確認ダイアログの表示状態
const [dialogOpen, setDialogOpen] = useState(false);
// ユーザアイコンURLが一致するなら自分の投稿
const isMyPost = useSession().data?.user?.image === post.user.iconUrl;
// ドロップダウンメニューの要素
const dropDownItems = [];
// ドロップダウンメニューの投稿削除ボタン
const dropDownDeleteButton = {
label: '投稿を削除',
onClick: () => setDialogOpen(true),
className: '',
icon: <MdDeleteForever />,
color: 'red',
};
// 自分の投稿ならドロップダウンに削除ボタン追加
if (isMyPost) {
dropDownItems.push(dropDownDeleteButton);
}
// セッションの取得
const session = useSession();
// ログイン状態
const isLoggedIn = session.status === 'authenticated';
// ログイン促進ダイアログの開閉状態
const [loginDialogOpen, setLoginDialogOpen] = useState(false);

return (
<div className={`${className} border-b border-gray-500 p-4`}>
@@ -49,18 +73,7 @@ const Post = ({ post, className }: PostProps) => {
<div className='ml-2 cursor-pointer items-center'>
<p className='text-lg text-black hover:underline'>{post.user.name}</p>
</div>
<DropDownButton
className='ml-auto flex'
items={[
{
label: '投稿を削除',
onClick: () => setDialogOpen(true),
className: '',
icon: <MdDeleteForever />,
color: 'red',
},
]}
></DropDownButton>
<DropDownButton className='ml-auto flex' items={dropDownItems}></DropDownButton>
</div>
{/* アイコン以外 */}
<div
@@ -100,7 +113,16 @@ const Post = ({ post, className }: PostProps) => {
{formatDateKanji(post.date)}
<div className='ml-auto flex items-center'>
<p className='mr-2 text-sm'>{post.miyabi.toLocaleString()}</p>
<MiyabiButton size='small' className='mr-0' />
<MiyabiButton
size='small'
onClick={() => {
if (isLoggedIn) {
} else {
setLoginDialogOpen(true);
}
}}
className='mr-0'
/>
</div>
</div>
{/* 拡大表示が有効の場合,モーダルを表示する */}
@@ -123,6 +145,8 @@ const Post = ({ post, className }: PostProps) => {
noText='いいえ'
/>
)}
{/* ログイン確認ダイアログ表示が有効の場合,ダイアログを表示する */}
{loginDialogOpen && <LoginDialog isOpen={loginDialogOpen} setIsOpen={setLoginDialogOpen} />}
</div>
);
};
100 changes: 81 additions & 19 deletions frontend/src/components/SideMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// クライアントコンポーネント
'use client';

import { CiUser, CiSettings, CiLogout } from 'react-icons/ci';
import { CiUser, CiSettings, CiLogout, CiLogin } from 'react-icons/ci';
import Image from 'next/image';
import { UserTypes } from '@/types/userTypes';
import { signIn, signOut, useSession } from 'next-auth/react';
import { useState } from 'react';
import Dialog from './Dialog';
import LoginDialog from './LoginDialog';

// props の型定義
interface SideMenuProps {
user: UserTypes;
className?: string;
style?: React.CSSProperties;
}
@@ -18,31 +20,91 @@ interface SideMenuProps {
* @param {SideMenuProps} props - ユーザデータを含むオブジェクト
* @return {JSX.Element} サイドメニューを表示するReactコンポーネント
*/
const SideMenu = ({ user, className, style }: SideMenuProps) => {
const SideMenu = ({ className, style }: SideMenuProps) => {
// セッションの取得
const session = useSession();
// ログイン状態
const isLoggedIn = session.status === 'authenticated';
// ログアウト確認ダイアログの開閉状態
const [logoutDialogOpen, setLogoutDialogOpen] = useState(false);
// ログイン促進ダイアログの開閉状態
const [loginDialogOpen, setLoginDialogOpen] = useState(false);

return (
<div className={`${className} w-40 space-y-3`} style={style}>
<div className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'>
<div
onClick={() => {
if (isLoggedIn) {
} else {
setLoginDialogOpen(true);
}
}}
className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'
>
<CiUser size={28} />
<a className='pl-1 text-xl'>プロフィール</a>
</div>
<div className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'>
<div
onClick={() => {
if (isLoggedIn) {
} else {
setLoginDialogOpen(true);
}
}}
className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'
>
<CiSettings size={28} />
<a className='pl-1 text-xl'>設定</a>
</div>
<div className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'>
<CiLogout size={28} />
<a className='pl-1 text-xl'>ログアウト</a>
</div>
<div className='flex items-center'>
<Image
src={user.iconUrl !== '' ? user.iconUrl : '/iconDefault.png'}
height={28}
width={28}
alt='Icon'
className='rounded-full'
{!isLoggedIn && (
<div
onClick={() => signIn()}
className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'
>
<CiLogin size={28} />
<a className='pl-1 text-xl'>ログイン</a>
</div>
)}
{isLoggedIn && (
<div
onClick={() => setLogoutDialogOpen(true)}
className='flex items-center rounded-lg bg-transparent hover:cursor-pointer hover:bg-black/5'
>
<CiLogout size={28} />
<a className='pl-1 text-xl'>ログアウト</a>
</div>
)}
{isLoggedIn && (
<div className='flex items-center'>
<Image
src={session.data?.user?.image ?? '/iconDefault.png'}
height={28}
width={28}
alt='Icon'
className='rounded-full'
/>
<a className='pl-1 text-xl'>{session.data?.user?.name ?? 'Name'}</a>
</div>
)}
{/* ログアウト確認ダイアログ表示が有効の場合,ダイアログを表示する */}
{logoutDialogOpen && (
<Dialog
isOpen={logoutDialogOpen}
title='ログアウト'
description='ログアウトしますか?'
yesCallback={() => {
setLogoutDialogOpen(false);
signOut();
}}
noCallback={() => {
setLogoutDialogOpen(false);
}}
yesText='はい'
noText='いいえ'
/>
<a className='pl-1 text-xl'>{user.name}</a>
</div>
)}
{/* ログイン確認ダイアログ表示が有効の場合,ダイアログを表示する */}
{loginDialogOpen && <LoginDialog isOpen={loginDialogOpen} setIsOpen={setLoginDialogOpen} />}
</div>
);
};