티스토리 뷰
이번에 계속 검색페이지 때문에 며칠을 이러고 있는지 모르겠다...
이제 막 배우기 시작한 나로써 그리고 제대로 공부한 것이 아니라 급하게 프로젝트를 하면서 배워야하기 때문에
더 어려운 것 같다. 솔직히 배운다기 보다 해결하기 위해 챗 GPT 사용하면서 그냥 익숙해지는 정도인 것 같은데
그정도만 해도 우선은 다행인 것 같다. 나중에 웹 개발 관련 수업을 하나 더 들어야겠다.
그 때를 생각하면 지금 익숙하게 하고 어느정도 눈에 익히는 것도 좋은 것 같다.
내가 너무 부족한 것이 느껴진다... 삼촌한테 많이 물어보며 어느정도 해결을 하긴 했는데...
삼촌 말대로 "일단 하고는 있는데 자기 자신이 상요하는 도구에 대해 이해가 많이 없다. 그럼 제일 쉽게 할 수 있는게 추측하는 것이 아니라 로그 찍어서 일일이 확인 하면서 해야한다" 였다....
진짜 너무너무너무 부족하다. 내일 삼촌이 수정해준 코드 보면서 어떤 식으로 되어있는지 이해하고 그걸 바탕으로...!!
1. 강의 탭 눌렀을 때 /search 로 리로드
2. 빈 값은 검색 결과가 없습니다. 나오게 하기
이렇게 2개를 해야하는데 2번은 조건문을...참...어떻게 써야할지.... 우선 삼촌이 수정해준 코드는...!! 그리고 내가 검색창 추가로 만들어서 그거에 대한 코드도 올리자
백엔드 추가한것도..애매하네 내일 실험을 한번 해보자!!!
<SearchPage.tsx>
import React, { ReactNode, useEffect, useState, useContext } from 'react';
import { useNavigate, useLocation, useSearchParams } from 'react-router-dom';
import Logger from 'console-log-level';
let log = Logger({level: 'trace'});
import {
Box,
Container,
Flex,
SimpleGrid,
Input,
Button,
IconButton,
useColorModeValue,
background,
} from '@chakra-ui/react';
import { SearchIcon } from '@chakra-ui/icons';
import { Text } from '@chakra-ui/react';
import axios from 'axios';
import ClassCard from '../../components/ClassCard';
import SectionTitle from '../../components/SectionTitle';
import ContentArea from '../../components/ContentArea';
import { API } from '../../../config';
import SearchBar from '../../components/SearchBar/SearchBar';
// 검색 정보에 대한 타입 정의
type CourseSearchInfo = {
title: string;
description: string;
courseId: number;
thumbnailPath: string;
tags: string;
userName: string;
};
const ClassCardList = ({ children }: { children: ReactNode }) => (
<SimpleGrid columns={{ base: 1, sm: 2, md: 3 }} spacing={5} gridAutoRows={'1fr'} borderColor={'none'}>
{children}
</SimpleGrid>
);
function SearchPage() {
const navigate = useNavigate();
const [searchResults, setSearchResults] = useState<CourseSearchInfo[]>([]);
// 검색 결과를 저장할 상태
const [keyword, setKeyword] = useState<string>('');
const [allResults, setAllResults] = useState<CourseSearchInfo[]>([]);
const [searchParams] = useSearchParams();
// useLocation을 활용하여 쿼리 스트링 값을 가져온다.
const location = useLocation();
useEffect(() => {
// search 속성에 접근하면 쿼리 스트링 값을 얻을 수 있다.
const keyWord = decodeURI(location.search);
console.log('keyWord===>', keyWord)
if (!!keyWord) {
// 검색어가 존재하는 경우에 API 경로에 쿼리 스트링으로 전달하여 fetch한다.
const fetchLectures = async () => {
try {
const getValue = API.COURSE_LIST_BY_SEARCH + keyWord
console.log('getValue===>',getValue)
const response = await axios.get(`${getValue}`);
//const data = await response.json();
setSearchResults(response.data.data);
console.log(searchResults);
} catch (error) {
console.error('검색 중 오류가 발생했습니다:', error);
}
};
fetchLectures();
} else {
// 검색어가 없는 경우 전체 게시물을 fetch한다.
const fetchLectures = async () => {
try {
const response = await axios(`${API.COURSE_LIST_BY_ALL}`); // 여기 좀 헷갈리네...
//const data = await response.json();
setSearchResults(response.data.data);
} catch (error) {
console.error('검색 중 오류가 발생했습니다:', error);
}
};
fetchLectures();
}
}, [location]);
return (
<>
<ContentArea>
<Flex flexDirection={'column'} className={'content-wrapper'} p={4} width={'100%'} gap={4}>
<SearchBar placeholder="검색어를 입력하세요" purpose="search" />
{/* 검색 결과를 보여줄지 여부를 조건부 렌더링으로 설정 */}
{searchResults.length > 0 ? (
<Box>
<SectionTitle title={'검색 결과'} />
<ClassCardList>
{searchResults.map((item, idx) => (
<ClassCard
key={idx}
title={item.title}
desc={item.description}
onClick={() => navigate(`/class/${item.courseId}`)}
imgSrc={item.thumbnailPath}
/>
))}
</ClassCardList>
<Box mt={250} />
</Box>
) : (
<Box>
{/* 전체 강의 목록을 보여줄 카드 리스트 */}
<SectionTitle title={'전체 강의'} />
<ClassCardList>
{allResults.map((item, idx) => (
<ClassCard
key={idx}
title={item.title}
desc={item.description}
onClick={() => navigate(`/class/${item.courseId}`)}
imgSrc={item.thumbnailPath}
/>
))}
</ClassCardList>
<Box mt={250} />
</Box>
)}
</Flex>
</ContentArea>
</>
);
}
export default SearchPage;
<SearchBar.tsx>
import React, { useState } from "react";
import { SearchIcon } from "@chakra-ui/icons"
import { useNavigate, useSearchParams } from "react-router-dom";
import { Box, Container, Flex, SimpleGrid, Input, Button, IconButton, useColorModeValue, background } from "@chakra-ui/react";
interface SearchBarPropsType {
placeholder: string;
purpose: string;
}
function SearchBar(props: SearchBarPropsType) {
const [searchKeyWord, setSearchKeyWord] = useState("");
// useSearchParams는 URL에 쿼리 스트링을 입력해준다.
const [searchParams, setSearchParams] = useSearchParams();
const navigate = useNavigate();
const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearchKeyWord(e.target.value);
};
const searchSubmitHandler = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// 검색 키워드가 존재하는 경우에만 setState를 진행한다.
if (!!searchKeyWord) {
setSearchParams({
keyword: searchKeyWord,
});
} else {
// 검색 키워드가 존재하지 않는 경우, 쿼리 스트링이 없는 원래 URL을 보여주도록 navigate 처리한다.
navigate(`${props.purpose === "search" ? "/search" : "/qa"}`); // 이 부분 수정해야한다!!!!!!
}
};
return (
<form onSubmit={searchSubmitHandler}>
<Box mx="auto" width="50%">
<Flex align="center" justify="center">
<input
type="text"
placeholder={props.placeholder}
value={searchKeyWord}
onChange={onChangeHandler}
style={{ padding: "8px", fontSize: "16px", borderRadius: "999px", width: "100%", paddingLeft: "20px" }}
/>
<Button
borderRadius="full"
bgColor={useColorModeValue("gray.200", "gray.700")}
_hover={{ bgColor: useColorModeValue("gray.300", "gray.600")}}
ml={2}
>
<SearchIcon />
</Button>
</Flex>
</Box>
</form>
);
}
export default SearchBar;
'SeSAC_도봉캠퍼스 > 새싹_도봉캠퍼스_프로젝트 4' 카테고리의 다른 글
2024.04.23_프로젝트 4 (22 일차) (0) | 2024.04.23 |
---|---|
2024.04.20_프로젝트 4 (19 일차) (0) | 2024.04.20 |
2024.04.19_프로젝트 4 (18 일차) (0) | 2024.04.19 |
2024.04.18_프로젝트 4 (17 일차) (0) | 2024.04.18 |
2024.04.17_프로젝트 4 (16 일차) (0) | 2024.04.18 |