Skip to content

Commit

Permalink
feat: AI評価機能
Browse files Browse the repository at this point in the history
  • Loading branch information
SatooRu65536 committed Nov 25, 2024
1 parent 3d41a9c commit 2e7e77c
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 102 deletions.
3 changes: 3 additions & 0 deletions src/app/(use-header)/codes/_components/view/Page/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useAtomValue } from 'jotai';
import SearchSection from '../SearchSection';
import { Card } from './Card';
import styles from './index.module.scss';
import { postListAtom } from '@/stores/postListAtom';
Expand All @@ -10,6 +11,8 @@ export default function Page() {

return (
<div className={styles.containers}>
<SearchSection />

{articles.map((post) => (
<Card key={post.id} post={post} />
))}
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import { useAtom } from 'jotai';
import { type KeyboardEvent, type ChangeEvent, useState } from 'react';
import styles from './index.module.scss';
import { searchTagWordsAtom } from '@/stores/postListAtom';

export default function SearchSection() {
const [searchWords, setSearchWords] = useAtom(searchTagWordsAtom);
const [value, setValue] = useState('');
const [isComposing, setIsComposing] = useState(false);

const onReturnKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key !== 'Enter') return;
if (isComposing) return;

setSearchWords([...searchWords, value]);
setValue('');
};

const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};

return (
<section className={styles.section}>
<p>
{searchWords.map((w) => (
<span key={w}>{w}</span>
))}
</p>
<input
onChange={onChange}
onCompositionEnd={() => {
setIsComposing(false);
}}
onCompositionStart={() => {
setIsComposing(true);
}}
onKeyDown={onReturnKeyDown}
type="text"
value={value}
/>
</section>
);
}
101 changes: 98 additions & 3 deletions src/stores/postListAtom.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { atom } from 'jotai';
import { type Post } from '@/types/post';
import type { Post } from '@/types/post';
import { supabase } from '@/utils/supabase/client';

const fetchPostList = async (): Promise<Post[]> => {
const fetchALlPostList = async (): Promise<Post[]> => {
const resPostList = await supabase.from('post').select(`
*,
language (
Expand Down Expand Up @@ -72,4 +72,99 @@ const fetchPostList = async (): Promise<Post[]> => {
});
};

export const postListAtom = atom(async () => await fetchPostList());
const fetchPostListByTag = async (searchWords: string[]): Promise<Post[]> => {
const orFilterByTag = searchWords.map((term) => `tag.ilike.%${term}%`).join(',');
const matchTagPostIds = await supabase.from('post_tag').select('post_id').or(orFilterByTag);

if (matchTagPostIds.data === null || matchTagPostIds.data.length === 0) {
return [];
}

const orFilterByTagId = matchTagPostIds.data?.map((matchTagPostId) => `id.eq.${matchTagPostId.post_id}`).join(',');

const resPostList = await supabase
.from('post')
.select(
`
*,
language (
id,
name
),
user (
id,
uid,
name
),
post_tag (
id,
tag
),
crazy_score (
score
)
`,
)
.or(orFilterByTagId);

if (resPostList.data === null) {
throw new Error('Error fetching data');
}

const averageCrazyScores: Array<{
post_id: number;
score: number;
}> = resPostList.data.map((post) => {
const sumScore = post.crazy_score.reduce((prev, current) => prev + current.score, 0);
const averageScore = sumScore / post.crazy_score.length;
return {
post_id: post.id,
score: averageScore,
};
});

return resPostList.data.map((resPost) => {
if (
resPost.language === null ||
resPost.user === null ||
resPost.post_tag === null ||
resPost.crazy_score === null
) {
throw new Error('Error fetching data');
}

const averageCrazyScore = averageCrazyScores.find((score) => score.post_id === resPost.id)?.score;
if (averageCrazyScore === undefined) {
throw new Error('Error averaging score is undefined');
}

const postTags = resPost.post_tag.map((tag) => ({
...tag,
post_id: resPost.id,
}));

return {
id: resPost.id,
code: resPost.code,
description: resPost.description,
title: resPost.title,
crazy_score: averageCrazyScore,
post_tags: postTags,
user: resPost.user,
language: resPost.language,
};
});
};

async function fetchPostList(searchWords: string[]): Promise<Post[]> {
if (searchWords.length === 0) return await fetchALlPostList();
return await fetchPostListByTag(searchWords);
}

export const searchTagWordsAtom = atom<string[]>([]);

export const postListAtom = atom(async (get) => {
const searchTagWords = get(searchTagWordsAtom);

return await fetchPostList(searchTagWords);
});
99 changes: 0 additions & 99 deletions src/stores/searchWordsAtom.ts

This file was deleted.

0 comments on commit 2e7e77c

Please sign in to comment.