Skip to content

Commit 54134f9

Browse files
authored
Merge pull request #69 from kc3hack/RAIT-09/develop
Rait 09/develop
2 parents 236295c + 1082266 commit 54134f9

File tree

9 files changed

+71
-72
lines changed

9 files changed

+71
-72
lines changed

backend/src/lib/gemini.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ const generateTanka = async (originalText: string): Promise<string[]> => {
103103
console.log(`短歌生成${i + 1}回目`);
104104

105105
const tanka = [
106-
jsonResponse.response[0].line1,
107-
jsonResponse.response[0].line2,
108-
jsonResponse.response[0].line3,
109-
jsonResponse.response[0].line4,
110-
jsonResponse.response[0].line5,
106+
jsonResponse.response[0].line1.replace('ッ', 'ツ'),
107+
jsonResponse.response[0].line2.replace('ッ', 'ツ'),
108+
jsonResponse.response[0].line3.replace('ッ', 'ツ'),
109+
jsonResponse.response[0].line4.replace('ッ', 'ツ'),
110+
jsonResponse.response[0].line5.replace('ッ', 'ツ'),
111111
];
112112

113113
const tankaYomi = [

frontend/next.config.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import type { NextConfig } from 'next';
33
const nextConfig: NextConfig = {
44
reactStrictMode: true,
55
images: {
6-
domains: ['avatars.githubusercontent.com'],
6+
domains: [
7+
'avatars.githubusercontent.com',
8+
'202502-test-bucket.s3.ap-northeast-1.amazonaws.com',
9+
],
710
},
811
experimental: {
912
serverActions: {

frontend/src/app/timeline/actions/fetchPosts.ts

+36-46
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,62 @@
11
// サーバアクション
22
'use server';
33

4+
import { hc } from 'hono/client';
5+
import { AppType } from '../../../../../backend/src/index';
46
import { PostTypes } from '@/types/postTypes';
57

8+
const client = hc<AppType>(process.env.BACKEND_URL ?? 'http://localhost:8080');
9+
610
/**
711
* 投稿データを取得する非同期関数
812
* @async
913
* @function fetchPosts
1014
* @param {Object} params - 投稿データ取得のためのパラメータオブジェクト
1115
* @param {number} params.limit - 取得する投稿の最大件数
16+
* @param {string} params.iconUrl - ユーザのアイコン画像URL
1217
* @param {string} params.offsetId - 取得を開始する投稿のID(オフセット)
1318
* @returns {Promise<PostTypes[]>} 投稿データの配列を返すPromise.投稿が存在しない場合は空配列を返す.
1419
*/
1520
const fetchPosts = async ({
1621
limit,
22+
iconUrl,
1723
offsetId,
1824
}: {
1925
limit: number;
20-
offsetId: string;
26+
iconUrl?: string;
27+
offsetId?: string;
2128
}): Promise<PostTypes[] | []> => {
22-
const posts = [
23-
{
24-
id: 'example_post',
25-
tanka: {
26-
line1: 'KANSAI',
27-
line2: '捉え難しき',
28-
line3: 'お題かな',
29-
line4: '古都の熱き歌',
30-
line5: 'アプリで詠まん',
31-
},
32-
original:
33-
'K.A.N.S.A.Iというお題、どう捉えていいのか難しかった。京都や奈良は昔から短歌がアツいのかな。短歌を使ったアプリ作ろうかな。',
34-
imageUrl: '',
35-
date: new Date(),
36-
user: {
37-
id: 'example_user',
38-
name: 'Name',
39-
bio: 'bio',
40-
iconUrl: '',
41-
},
42-
miyabi: 2222,
43-
},
44-
{
45-
id: 'example_post',
46-
tanka: {
47-
line1: 'KANSAI',
48-
line2: '捉え難しき',
49-
line3: 'お題かな',
50-
line4: '古都の熱き歌',
51-
line5: 'アプリで詠まん',
29+
try {
30+
const res = await client.timeline.$post({
31+
json: {
32+
limit: limit,
33+
my_icon: iconUrl,
34+
post_id: offsetId,
5235
},
53-
original:
54-
'K.A.N.S.A.Iというお題、どう捉えていいのか難しかった。京都や奈良は昔から短歌がアツいのかな。短歌を使ったアプリ作ろうかな。',
55-
imageUrl: '/imageSample.jpg',
56-
date: new Date(),
36+
});
37+
console.log(`Loading more Posts... limit: ${limit}, offsetId: ${offsetId}`);
38+
39+
// エラーがある場合は空の配列を返す
40+
if (!res.ok) {
41+
console.log(res.statusText);
42+
return [];
43+
}
44+
45+
const json = await res.json();
46+
return json.posts.map((post) => ({
47+
...post,
48+
id: post.id,
49+
tanka: post.tanka,
50+
original: post.original,
51+
imageUrl: post.image_path ?? '',
52+
date: new Date(post.created_at),
5753
user: {
58-
id: 'example_user',
59-
name: 'Name',
60-
bio: 'bio',
61-
iconUrl: '',
54+
name: post.user_name,
55+
iconUrl: post.user_icon,
6256
},
63-
miyabi: 22,
64-
},
65-
];
66-
console.log(`Loading more Posts... limit: ${limit}, offsetId: ${offsetId}`);
67-
68-
try {
69-
return [...posts, ...posts, ...posts, ...posts, ...posts];
57+
miyabiCount: post.miyabi_count,
58+
miyabiIsClicked: post.is_miyabi,
59+
}));
7060
} catch (error) {
7161
console.error(error);
7262
return [];

frontend/src/app/timeline/page.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,14 @@ const Timeline = () => {
4646
const loadMorePosts = useCallback(async () => {
4747
setIsLoading(true);
4848
// 投稿データを取得
49-
const newPosts = await fetchPosts({ limit: LIMIT, offsetId });
49+
const newPosts = await fetchPosts({
50+
limit: LIMIT,
51+
iconUrl: session.data?.user?.id,
52+
offsetId: offsetId,
53+
});
5054
if (newPosts && newPosts.length > 0) {
5155
setPosts((prevPosts) => [...prevPosts, ...newPosts]);
52-
setOffsetId(() => newPosts[1].id);
56+
setOffsetId(() => newPosts[newPosts.length - 1].id);
5357
// 取得した投稿数がLIMIT未満の場合は,これ以上取得できる投稿は無い.
5458
if (newPosts.length < LIMIT) {
5559
setHasMore(false);
@@ -112,7 +116,7 @@ const Timeline = () => {
112116
{/* タイムライン */}
113117
<div className='pt-12'>
114118
<div className='relative mx-auto max-w-lg'>
115-
<SideMenu className='absolute top-5 hidden lg:block' style={{ left: '-12rem' }} />
119+
<SideMenu className='fixed top-16 hidden -translate-x-full lg:block' />
116120
<PostList posts={posts} className='mx-auto max-w-sm lg:max-w-lg' />
117121
{isLoading && <p className='py-3 text-center'>投稿を取得中...</p>}
118122
<div ref={targetRef} className='h-px' />

frontend/src/components/GifButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ const GifButton = ({
3737
setIsAnimationPlaying(false);
3838
setIsClicked(true);
3939
}, animationDuration);
40-
onClick?.();
4140
};
4241

4342
const cancelButton = () => {
@@ -46,6 +45,7 @@ const GifButton = ({
4645
};
4746

4847
const switchButton = () => {
48+
if (isAnimationPlaying) return;
4949
if (isClicked) {
5050
cancelButton();
5151
onCancel?.();

frontend/src/components/Post.tsx

+15-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import React from 'react';
55
import { useState } from 'react';
66
import Image from 'next/image';
77
import { PostTypes } from '@/types/postTypes';
8-
import { TankaTypes } from '@/types/tankaTypes';
98
import ImageModal from '@/components/ImageModal';
109
import MiyabiButton from '@/components/MiyabiButton';
1110
import DropDownButton from './DropDownButton';
@@ -32,6 +31,8 @@ const Post = ({ post, className }: PostProps) => {
3231
const tanka = parseTanka(post.tanka);
3332
// 投稿に画像が含まれるか
3433
const hasImage = Boolean(post.imageUrl);
34+
// 雅カウントの状態
35+
const [miyabiCount, setMiyabiCount] = useState(post.miyabiCount);
3536
// 画像の拡大表示状態
3637
const [modalOpen, setModalOpen] = useState(false);
3738
// 削除確認ダイアログの表示状態
@@ -112,15 +113,24 @@ const Post = ({ post, className }: PostProps) => {
112113
<div className='mt-3 flex items-center text-black'>
113114
{formatDateKanji(post.date)}
114115
<div className='ml-auto flex items-center'>
115-
<p className='mr-2 text-sm'>{post.miyabi.toLocaleString()}</p>
116+
<p className='mr-2 text-sm'>{miyabiCount.toLocaleString()}</p>
116117
<MiyabiButton
117118
size='small'
118119
onClick={() => {
119120
if (isLoggedIn) {
121+
setMiyabiCount((count) => ++count);
120122
} else {
121123
setLoginDialogOpen(true);
122124
}
123125
}}
126+
onCancel={() => {
127+
if (isLoggedIn) {
128+
setMiyabiCount((count) => --count);
129+
} else {
130+
setLoginDialogOpen(true);
131+
}
132+
}}
133+
initialIsClicked={post.miyabiIsClicked}
124134
className='mr-0'
125135
/>
126136
</div>
@@ -154,11 +164,11 @@ const Post = ({ post, className }: PostProps) => {
154164
/**
155165
* 短歌をパースして,改行と全角空白を追加する.
156166
* @function parseTanka
157-
* @param {TankaTypes} tanka - 短歌型オブジェクト
167+
* @param {Array<string>} tanka - 短歌の配列
158168
* @return {string} パースされた短歌の文字列
159169
*/
160-
const parseTanka = (tanka: TankaTypes): string => {
161-
const parsedTanka: string = `${tanka.line1}\n\u3000${tanka.line2}\n\u3000\u3000${tanka.line3}\n${tanka.line4}\n\u3000${tanka.line5}`;
170+
const parseTanka = (tanka: Array<string>): string => {
171+
const parsedTanka: string = `${tanka[0]}\n\u3000${tanka[1]}\n\u3000\u3000${tanka[2]}\n${tanka[3]}\n\u3000${tanka[4]}`;
162172
return parsedTanka;
163173
};
164174

frontend/src/types/postTypes.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { UserTypes } from '@/types/userTypes';
2-
import { TankaTypes } from '@/types/tankaTypes';
32

43
export type PostTypes = {
54
id: string;
6-
tanka: TankaTypes;
5+
tanka: Array<string>;
76
original: string;
87
imageUrl: string;
98
date: Date;
109
user: UserTypes;
11-
miyabi: number;
10+
miyabiCount: number;
11+
miyabiIsClicked: boolean;
1212
};

frontend/src/types/tankaTypes.ts

-7
This file was deleted.

frontend/src/types/userTypes.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export type UserTypes = {
22
name: string;
3-
bio: string;
43
iconUrl: string;
54
};

0 commit comments

Comments
 (0)