삭제전 저장(동아리까지 완성본)

류한선·2024년 6월 2일

4차 프로젝트

목록 보기
49/53

article

'use client'

import Link from 'next/link'
import api from "@/util/api"
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import DefaultLayout from "@/components/Layouts/DefaultLayout";

export default function Article() {
 
    const getArticles = async () => {
        return await api.get('/api/v1/articles')
            .then((response) => response.data.data.articles)
    }

    const {isLoading, error, data} = useQuery({
        queryKey: ['articles'],
        queryFn: getArticles
    });


    const deleteArticle = async (id) => {
        await api.delete(`/api/v1/articles/${id}`)
    }

    const queryClient = useQueryClient()
    const mutation = useMutation({
        mutationFn: deleteArticle,
        onSuccess: () => {
            queryClient.invalidateQueries({queryKey: ['articles']})
        }
    })

    if (error) {
        console.log(error)
    }

    if (isLoading) <>Loading...</>

    if (data) {
        return (
            <DefaultLayout>
                <ul>
                    번호 / 제목 / 작성자 / 생성일 / 삭제
                    {data.map((row) => (
                        <li key={row.id}>
                            {row.id} /{' '}
                            <Link href={`/article/${row.id}`}>{row.subject}</Link> /{' '}
                            {row.author} / {row.createdDate}
                            <button onClick={() => mutation.mutate(row.id)}>
                                삭제
                            </button>
                        </li>
                    ))}
                </ul>
                <Link href="/clubCreate">
    Club Create 페이지로 이동
</Link>
                <Link href="/articleCreate">
    Article Create 페이지로 이동
</Link>
            </DefaultLayout>
        )
    }


}

[id]

'use client'

import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import api from "@/util/api";
import DefaultLayout from "@/components/Layouts/DefaultLayout";
import Link from 'next/link'

export default function ArticleDetail() {
    const params = useParams();

    const getArticle = async () => {
        return await api.get(`/api/v1/articles/${params.id}`)
            .then((response) => response.data.data.article);
    }

    const { isLoading: articleLoading, error: articleError, data: articleData } = useQuery({
        queryKey: ['article', params.id],
        queryFn: getArticle
    });
    
    const getAnswers = async () => {
        return await api.get(`/api/v1/answers/${params.id}/articles`)
            .then((response) => response.data.data.answers);
    }

    const { isLoading: answerLoading, error: answerError, data: answerData, refetch } = useQuery({
        queryKey: ['answers', params.id],
        queryFn: getAnswers
    });

    const [answer, setAnswer] = useState({ content: '' });

    const handleSubmit = async (e) => {
        e.preventDefault();
        await api
            .post('/api/v1/answers', { ...answer, article: { id: params.id } })
            .then((response) => {
                console.log(response);
                setAnswer({ content: '' });
                refetch();  // 새로운 답변 작성 후 답변 리스트를 다시 불러옴
            })
            .catch((error) => {
                console.log(error);
            });
    };

    const handleChange = (e) => {
        const { name, value } = e.target;
        setAnswer({ ...answer, [name]: value });
    };

    if (articleError || answerError) {
        console.log(articleError || answerError);
    }

    if (articleLoading || answerLoading) {
        return <>Loading...</>;
    }

    return (
        <DefaultLayout>
            {articleData && (
                <>
                    <h1>게시판 상세 {params.id}번</h1>
                    <div>{articleData.subject}</div>
                    <div>{articleData.content}</div>

                    <Link href={`/article/${params.id}/edit`}>수정하기</Link>
                </>
            )}

            <h3>답글 작성</h3>
            <form onSubmit={handleSubmit}>
                <div>
                    <label>내용:</label>
                    <textarea name="content" value={answer.content} onChange={handleChange} />
                </div>
                <button type="submit">등록</button>
            </form>

            <h3>답글 목록</h3>
            {answerData && answerData.length > 0 ? (
                answerData.map((answer, index) => (
                    <div key={index}>
                        <div>{answer.content}</div>
                    </div>
                ))
            ) : (
                <div>답글이 없습니다.</div>
            )}
        </DefaultLayout>
    );
}

edit

'use client'

import api from "@/util/api"
import { useParams } from 'next/navigation'
import { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation';
import DefaultLayout from "@/components/Layouts/DefaultLayout";

export default function ArticleEdit() {
    const params = useParams()
    const router = useRouter();

    const [isLoading, setIsLoading] = useState(false)
    const [article, setArticle] = useState({ subject: '', content: '' })

    useEffect(() => {
        fetchArticle()
    }, [])

    const fetchArticle = async () => {
        try {
            const response = await api.get(`/api/v1/articles/${params.id}`)
            setArticle(response.data.data.article)
            setIsLoading(true)
        } catch (error) {
            console.log(error)
        }
    }

    const handleSubmit = async (e) => {
        e.preventDefault()
        try {
            await api.patch(`/api/v1/articles/${params.id}`, article)
            router.push('/article');
        } catch (error) {
            console.log(error)
        }
    }

    const handleChange = (e) => {
        const { name, value } = e.target
        setArticle({ ...article, [name]: value })
    }

    return (
        <DefaultLayout>
            {isLoading ? (
                <>
                    <h1>수정페이지</h1>
                    <form onSubmit={handleSubmit}>
                        <input
                            type="text"
                            name="subject"
                            value={article.subject}
                            onChange={handleChange}
                        />
                        <input
                            type="text"
                            name="content"
                            value={article.content}
                            onChange={handleChange}
                        />
                        <button type="submit">수정</button>
                    </form>
                </>
            ) : (
                <></>
            )}
        </DefaultLayout>
    )
}

articleCreate

'use client'

import { useState } from 'react';
import api from '@/util/api';
import { useRouter, useParams } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import DefaultLayout from "@/components/Layouts/DefaultLayout";

export default function ClubArticleCreate() {
    const router = useRouter();
    const params = useParams(); // 클럽 ID를 가져옴
    const [article, setArticle] = useState({ subject: '', content: ''});

    const getClub = async () => {
        return await api.get(`/api/v1/articles/${params.id}`)
            .then((response) => response.data.data.article);
    }

    const { isLoading: clubLoading, error: clubError, data: clubData } = useQuery({
        queryKey: ['club', params.id],
        queryFn: getClub
    });

    // const handleSubmit = async (e) => {
    //     e.preventDefault();
    //     try {
    //         await api.post('/api/v1/articles', { ...article, club: { id: params.id } })
    //         .then((response) => {
    //             console.log(response);
    //             setArticle({ subject: '', content: ''});
                
    //         })
    //         router.push(`/article`);
    //     } catch (error) {
    //         console.error('등록 중 에러:', error);
    //     }
    // };

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            await api.post('/api/v1/articles', article);
            // 등록 성공 시, 이전 페이지로 이동하거나 사용자에게 알림을 제공할 수 있습니다.
            router.push('/article');
        } catch (error) {
            console.error('등록 중 에러:', error);
        }
    };

    const handleChange = (e) => {
        const { name, value } = e.target;
        setArticle({ ...article, [name]: value });
    };

    return (
        <DefaultLayout>
            <h3>게시글 등록</h3>
            <form onSubmit={handleSubmit}>
                <div>
                    <label>제목:</label>
                    <input type="text" name="subject" value={article.subject} onChange={handleChange} />
                </div>
                <div>
                    <label>내용:</label>
                    <textarea name="content" value={article.content} onChange={handleChange} />
                </div>
                <button type="submit">등록</button>
            </form>
        </DefaultLayout>
    );
}

club

'use client'

import Link from 'next/link';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import api from "@/util/api";
import DefaultLayout from "@/components/Layouts/DefaultLayout";

export default function Club() {
    const getClubs = async () => {
        try {
            const response = await api.get('/api/v1/clubs');
            return response.data.data.club; // 클럽 목록 가져오기
        } catch (error) {
            throw new Error('Failed to fetch clubs');
        }
    };

    const { isLoading, error, data } = useQuery({
        queryKey: ['clubs'],
        queryFn: getClubs
    });

    const deleteClub = async (id) => {
        await api.delete(`/api/v1/clubs/${id}`);
    };

    const queryClient = useQueryClient();
    const mutation = useMutation({
        mutationFn: deleteClub,
        onSuccess: () => {
            queryClient.invalidateQueries({ queryKey: ['clubs'] });
        }
    });

    if (error) {
        console.error(error);
    }

    if (isLoading) {
        return <>Loading...</>;
    }

    if (error) {
        console.error(error);
        return <>Error occurred: {error.message}</>;
    }

    if (!data || data.length === 0) {
        return <>No data available</>;
    }

    return (
        <DefaultLayout>
            <ul>
                {data.map((row) => (
                    <li key={row.id}>
                        {row.id} /{' '}
                        <Link href={`/club/${row.id}`}>{row.clubName}</Link> /{' '}
                        {row.author} / {row.createdDate}
                        <button onClick={() => mutation.mutate(row.id)}>
                            삭제
                        </button>
                    </li>
                ))}
            </ul>
            <Link href="/clubCreate">
                Club Create 페이지로 이동
            </Link>
        </DefaultLayout>
    );
}

[id]

'use client'

import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import api from "@/util/api";
import DefaultLayout from "@/components/Layouts/DefaultLayout";
import Link from 'next/link'

export default function ClubDetail() {
    const params = useParams();

    const getClub = async () => {
        return await api.get(`/api/v1/clubs/${params.id}`)
            .then((response) => response.data.data.club);
    }

    const { isLoading: clubLoading, error: clubError, data: clubData } = useQuery({
        queryKey: ['club', params.id],
        queryFn: getClub
    });
    
    const getArticles = async () => {
        return await api.get(`/api/v1/articles/${params.id}/clubs`)
            .then((response) => response.data.data.articles);
    }

    const { isLoading: articleLoading, error: articleError, data: articleData, refetch } = useQuery({
        queryKey: ['articles', params.id],
        queryFn: getArticles
    });

    const [article, setArticle] = useState({ subject: '', content: ''});

    const handleSubmit = async (e) => {
        e.preventDefault();
        await api
            .post('/api/v1/articles', { ...article, club: { id: params.id } })
            .then((response) => {
                console.log(response);
                setArticle({ subject: '', content: '' });
                refetch();  // 새로운 답변 작성 후 답변 리스트를 다시 불러옴
            })
            .catch((error) => {
                console.log(error);
            });
    };

    const handleChange = (e) => {
        const { name, value } = e.target;
        setArticle({ ...article, [name]: value });
    };

    if (articleError || clubLoading) {
        console.log(articleError || clubLoading);
    }

    if (articleLoading || clubLoading) {
        return <>Loading...</>;
    }

    return (
        <DefaultLayout>
            {clubData && (
                <>
                    <h1>동아리 상세 {params.id}번</h1>
                    
                    <div>{clubData.clubName}</div>

                    <Link href={`/article/${params.id}/edit`}>수정하기</Link>
                </>
            )}

            <h3>게시글 작성</h3>
            <form onSubmit={handleSubmit}>
            <div>
                    <label>제목:</label>
                    <input type="text" name="subject" value={article.subject} onChange={handleChange} />
                </div>
                <div>
                    <label>내용:</label>
                    <textarea name="content" value={article.content} onChange={handleChange} />
                </div>
                <button type="submit">등록</button>
            </form>
            <Link href={`/club/${params.id}/articleForm`}>테스트</Link>
            <h3>게시글 목록</h3>
            {articleData && articleData.length > 0 ? (
                articleData.map((article, index) => (
                    <div key={index}>
                        <Link href={`/club/${article.id}/detail`}>{article.subject}</Link>
                        <div>{article.content}</div>
                    </div>
                ))
            ) : (
                <div>답글이 없습니다.</div>
            )}
        </DefaultLayout>
    );
}

detail

'use client'

import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import api from "@/util/api";
import DefaultLayout from "@/components/Layouts/DefaultLayout";
import Link from 'next/link'

export default function ArticleDetail() {
    const params = useParams();

    const getArticle = async () => {
        return await api.get(`/api/v1/articles/${params.id}`)
            .then((response) => response.data.data.article);
    }

    const { isLoading: articleLoading, error: articleError, data: articleData } = useQuery({
        queryKey: ['article', params.id],
        queryFn: getArticle
    });
    
    const getAnswers = async () => {
        return await api.get(`/api/v1/answers/${params.id}/articles`)
            .then((response) => response.data.data.answers);
    }

    const { isLoading: answerLoading, error: answerError, data: answerData, refetch } = useQuery({
        queryKey: ['answers', params.id],
        queryFn: getAnswers
    });

    const [answer, setAnswer] = useState({ content: '' });

    const handleSubmit = async (e) => {
        e.preventDefault();
        await api
            .post('/api/v1/answers', { ...answer, article: { id: params.id } })
            .then((response) => {
                console.log(response);
                setAnswer({ content: '' });
                refetch();  // 새로운 답변 작성 후 답변 리스트를 다시 불러옴
            })
            .catch((error) => {
                console.log(error);
            });
    };

    const handleChange = (e) => {
        const { name, value } = e.target;
        setAnswer({ ...answer, [name]: value });
    };

    if (articleError || answerError) {
        console.log(articleError || answerError);
    }

    if (articleLoading || answerLoading) {
        return <>Loading...</>;
    }

    return (
        <DefaultLayout>
            {articleData && (
                <>
                    <h1>게시판 상세 {params.id}번</h1>
                    <div>{articleData.subject}</div>
                    <div>{articleData.content}</div>

                    <Link href={`/article/${params.id}/edit`}>수정하기</Link>
                </>
            )}

            <h3>답글 작성</h3>
            <form onSubmit={handleSubmit}>
                <div>
                    <label>내용:</label>
                    <textarea name="content" value={answer.content} onChange={handleChange} />
                </div>
                <button type="submit">등록</button>
            </form>

            <h3>답글 목록</h3>
            {answerData && answerData.length > 0 ? (
                answerData.map((answer, index) => (
                    <div key={index}>
                        <div>{answer.content}</div>
                    </div>
                ))
            ) : (
                <div>답글이 없습니다.</div>
            )}
        </DefaultLayout>
    );
}

articleForm

'use client'

import { useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import api from "@/util/api";
import DefaultLayout from "@/components/Layouts/DefaultLayout";

export default function ArticleForm() {
    const params = useParams();
    const router = useRouter();
    
    const [article, setArticle] = useState({ subject: '', content: '' });

    const handleSubmit = async (e) => {
        e.preventDefault();
        await api
            .post('/api/v1/articles', { ...article, club: { id: params.id } })
            .then((response) => {
                console.log(response);
                setArticle({ subject: '', content: '' });
                router.push(`/club/${params.id}`);
            })
            .catch((error) => {
                console.log(error);
            });
    };

    const handleChange = (e) => {
        const { name, value } = e.target;
        setArticle({ ...article, [name]: value });
    };

    return (
        <DefaultLayout>
            <h3>게시글 작성</h3>
            <form onSubmit={handleSubmit}>
                <div>
                    <label>제목:</label>
                    <input type="text" name="subject" value={article.subject} onChange={handleChange} />
                </div>
                <div>
                    <label>내용:</label>
                    <textarea name="content" value={article.content} onChange={handleChange} />
                </div>
                <button type="submit">등록</button>
            </form>
        </DefaultLayout>
    );
}

clubCreate

'use client'

import Link from 'next/link'
import { useEffect, useState } from 'react'
import api from "@/util/api"
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import DefaultLayout from "@/components/Layouts/DefaultLayout";
import { useRouter } from 'next/navigation';

export default function ClubCreate() {
    const router = useRouter();
    const [club, setClub] = useState({  clubName: '' });

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            await api.post('/api/v1/clubs', club);
            // 등록 성공 시, 이전 페이지로 이동하거나 사용자에게 알림을 제공할 수 있습니다.
            router.push('/club');
        } catch (error) {
            console.error('등록 중 에러:', error);
        }
    };

    const handleChange = (e) => {
        const { name, value } = e.target;
        setClub({ ...club, [name]: value });
    };

    return (
        <DefaultLayout>
            <h3>동아리 등록</h3>
            <form onSubmit={handleSubmit}>
                
                <div>
                    <label>내용:</label>
                    <textarea name="clubName" value={club.clubName} onChange={handleChange} />
                </div>
                <button type="submit">등록</button>
            </form>
        </DefaultLayout>
    );

}

0개의 댓글