評価値の登録
API
評価値登録API
frontend/src/services/ratings/postRating.ts
import { ApiContext, Movie, User } from '@/types/data';
import { fetcher } from '@/utils';
const context: ApiContext = {
apiRootUrl: process.env.NEXT_PUBLIC_API_BASE_URL,
};
/**
* 評価値登録API
* @param user ユーザ
* @param movie 映画
* @param rating 評価値
*/
const postRating = async (user: User, movie: Movie, rating: number) => {
const id = user.id + '_' + String(movie.id).padStart(6, '0');
const body = {
id: id,
user_id: user.id,
movie_id: movie.id,
rating: rating,
};
await fetcher(`${context.apiRootUrl?.replace(/\/$/g, '')}/ratings/`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
};
export default postRating;
コンポーネント
スターコンポーネント
frontend/src/app/components/rating/Star.tsx
...(略)...
type Props = {
index: number;
width: number;
rating: number;
setRating: Function;
handleRatingClick: Function; // <- 追加
};
const Star = (props: Props) => {
const handleRatingClick = async () => {
const rating = (props.index + 1) / 2;
await props.setRating(rating);
props.handleRatingClick(rating); // <- 追加
};
...(略)...
};
export default Star;
評価値コンポーネント
frontend/src/app/components/rating/StarRating.tsx
...(略)...
type Props = {
starWidth: number;
rating: number;
handleRatingClick: Function; // <- 追加
};
const StarRating = (props: Props) => {
const [rating, setRating] = useState<number>(props.rating);
return (
<>
<div className="flex">
{(function () {
const stars = [];
for (let i = 0; i < 10; i++) {
stars.push(
<Star
key={i}
index={i}
width={props.starWidth}
rating={rating}
setRating={setRating}
handleRatingClick={props.handleRatingClick} // <- 追加
/>
);
}
return <div>{stars}</div>;
})()}
</div>
</>
);
};
export default StarRating;
映画詳細カードコンポーネント
frontend/src/app/components/movie/MovieCardDetail.tsx
'use client'; // <- 追加
import { Movie, User } from '@/types/data';
import Image from 'next/image';
import React from 'react';
import StarRating from '../rating/StarRating';
import postRating from '@/services/ratings/postRating'; // <- 追加
...(略)...
const MovieCardDetail = (props: Props) => {
const img_url = '/img/dummy_poster.png';
// ↓追加
const handleRatingClick = async (rating: number) => {
await postRating(props.user, props.movie, rating);
};
// ↑追加
return (
<>
<article key={props.movie.id}>
...(略)...
{props.user ? (
<StarRating
starWidth={STAR_WIDTH}
rating={props.movie.rating?.rating}
handleRatingClick={handleRatingClick} // <- 追加
/>
) : (
<></>
)}
</article>
</>
);
};
export default MovieCardDetail;
映画カードコンポーネント
frontend/src/app/components/movie/MovieCard.tsx
import { Movie, User } from '@/types/data';
import Image from 'next/image';
import Link from 'next/link';
import React from 'react';
import StarRating from '../rating/StarRating';
import postRating from '@/services/ratings/postRating'; // <- 追加
...(略)...
const MovieCard = (props: Props) => {
const img_url = '/img/dummy_poster.png';
// ↓追加
const handleRatingClick = async (rating: number) => {
await postRating(props.user, props.movie, rating);
};
// ↑追加
return (
<>
<article className="h-72 w-32 shadow" key={props.movie.id}>
...(略)...
{props.user ? (
<StarRating
starWidth={STAR_WIDTH}
rating={props.movie.rating?.rating}
handleRatingClick={handleRatingClick} // <- 追加
/>
) : (
<></>
)}
...(略)...
</article>
</>
);
};
export default MovieCard;
ブラウザで下記URLにアクセスしてください。
サインイン後、任意の評価値をクリックすると、下記のようにratings
テーブルに評価値が登録されます。下記の例では、movie_id=1
の映画に対して、評価値4.5
を与えています。
recsys_full=# SELECT * FROM ratings;
id | rating | rated_at | movie_id | user_id
-------------------+--------+-------------------------------+----------+-------------
【ユーザID】_000001 | 4.5 | 2025-03-22 16:23:06.366922+09 | 1 | 【ユーザID】
...(略)...
ブラウザで下記URLにアクセスしてください。
同様に、映画リスト上でも任意の評価値をクリックすることで、ratings
テーブルに評価値が登録されます。ただし、現時点では、バックエンドサーバから評価値を取得していませんので、映画リスト上で評価値を更新しても、ブラウザを更新したり、ページを切り替えると、元の表示に戻ります。