728x90
[나만무] 검색 기능
Front
쿼리 전달
features/Dashboard/components/SearchBar.tsx
import React, { useState, KeyboardEvent } from "react";
import { useRouter } from "next/router";
export default function SearchBar() {
...
const [keywords, setKeywords] = useState("");
const onKeyPress = (e: KeyboardEvent) => {
if (e.key == "Enter") {
e.preventDefault();
router.push({
pathname: '/search',
query: {search : keywords.replace(/[^ㄱ-ㅎ가-힣a-zA-Z0-9]/g, " ")}
});
setKeywords("");
setSearchBar(false);
}
};
return (
<>
...
<input
ref={inputRef}
type="text"
className="w-full h-10 font-medium bg-transparent outline-none ring-none"
value={keywords}
placeholder="검색"
onChange={(e) => {
setKeywords(e.target.value);
}}
onBlur={() => setSearchBar(false)}
onKeyPress={onKeyPress}
/>
...
</>
);
}
next로 페이지 전환하면서 query 전달
router.push({
pathname: '/search',
query: {search : keywords.replace(/[^ㄱ-ㅎ가-힣a-zA-Z0-9]/g, " ")}
});
pages/search.tsx
import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
import axios from "axios";
// Component
import NavBar from "../features/Dashboard/components/NavBar";
import { Wrapper } from "@/styles/wrapper";
import SearchResult from "@/features/Search/ContentSearch";
// Assets
import { GrFormNext } from "react-icons/gr";
interface ResponseData {
hasNext: boolean;
results: {
cardTags: string[];
cardKeyword: string;
cardContent: string;
}[];
}
export default function Search() {
const router = useRouter();
const keywords = router.query.search;
const [contentsData, setContentsData] = useState<ResponseData | null>(null);
const [tagsData, setTagsData] = useState<ResponseData | null>(null);
const [contentsAllData, setContensAllData] = useState<ResponseData | null>(
null
);
const [tagsAllData, setTagsAllData] = useState<ResponseData | null>(null);
useEffect(() => {
const contentsData = async () => {
try {
const response = await axios.get(
"http://localhost:8800/dashboard/contents",
{
params: {
search: keywords,
},
}
);
setContentsData(response.data);
} catch (error) {
console.error(error); // Handle any errors that occurred during the request
}
};
if (keywords) {
contentsData();
}
}, [keywords]);
return (
...
{contentsData?.results[0] ? (
<SearchResult data={contentsData?.results} />
) : (
<div>검색 결과가 없습니다.</div>
)}
....
);
}
Back 데이터 가공
routes/search.js
import express from 'express';
import '../dotenv.js';
import { db } from '../connect.js';
import { searchContent , searchTag} from '../db/searchQueries.js';
const router = express.Router();
router.get('/contents', async (req, res) => {
// console.log(req.query);
const { search } = req.query;
let connection = null;
try {
connection = await db.getConnection();
const [ result ] = await connection.query(searchContent(search));
let arr = [];
for (let i = 0; i < result.length / 2; i++) {
arr.push({
cardTags: [result[i * 2].tag, result[i + 1].tag],
cardKeyword: "# 1",
cardContent: result[i * 2].content,
});
}
// console.log(arr[0]);
return res.send({results: [arr[0]]});
} catch(err) {
connection?.release();
console.log(err);
res.status(500).send('Internal Server Error');
}
});
db/searchQueries.js
export const searchContent = (keyword) => {
return `SELECT f.file_id, f.content, t.tag
FROM File f
JOIN FileTag ft ON f.file_id = ft.file_id
JOIN Tag t ON ft.tag_id = t.tag_id
WHERE f.content LIKE '%${keyword}%'
ORDER BY f.updated_at ASC;`;
};
반복되는 코드가 많고 기능이 원할하게 흘러가려면 좀더 디벨롭해야할듯하다.
일단 유저 모달창 만들고! 해당 코드 수정할 예정!
'project > insightLINK' 카테고리의 다른 글
[나만무] node Logging System (0) | 2023.06.25 |
---|---|
[나만무] Next Auth, google social login 구현 (0) | 2023.06.19 |
[나만무] Google Social 로그인 (0) | 2023.06.10 |
[나만무] 로그인 - 로그아웃 (0) | 2023.06.09 |