Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/@types/models/getSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { AssetGroupSymbol, AssetTypeSymbol } from "./assetSymbol";
import { CategoryTypeSymbol } from "./categoryTypeSymbol";

/**
* 검색 조회 Response Interface
*/

export type GetSearchItems = GetSearchItem[];

export type GetSearchItem = {
accountId: number;
categoryName: string;
assetGroup: AssetGroupSymbol;
assetType: AssetTypeSymbol;
assetName: string;
amount: number;
transactionType: CategoryTypeSymbol;
transactionDetail: string;
transactedAt: string;
address: string;
memo: string;
imageIds: number[];
recurringType: string;
isInstallment: boolean;
installmentMonth: number;
createdAt: string;
updatedAt: string;
latitude: string;
longitude: string;
};
5 changes: 3 additions & 2 deletions src/components/Common/DayIncomeExpenseInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { GetSearchItem } from "@/src/@types/models/getSearch";
import { theme } from "../../../assets/theme";
import { AccountsData } from "../DayIncomeExpenseInfos";
import { DayIncomeExpenseInfoUI } from "./style";
import { ChangeNumberForAccounting, ChangeTime } from "@/src/assets/util";

interface DayIncomeExpenseInfoProps {
onClick: (item: AccountsData) => void;
item: AccountsData;
onClick: (item: AccountsData | GetSearchItem) => void;
item: AccountsData | GetSearchItem;
}

function DayIncomeExpenseInfo({ onClick, item }: DayIncomeExpenseInfoProps) {
Expand Down
30 changes: 25 additions & 5 deletions src/components/Common/DayIncomeExpenseInfos/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useRecoilState } from "recoil";
import DayIncomeExpenseInfo from "../DayIncomeExpenseInfo";
import { searchResultDataAtom } from "@/src/hooks/recoil/searchResultData";
import { searchKeywordClickedState } from "@/src/hooks/recoil/searchKeywordClickedState";
import { GetSearchItem } from "@/src/@types/models/getSearch";
import { DayIncomeExpenseInfosUI } from "./style";

export interface AccountsData {
accountId: number;
Expand Down Expand Up @@ -56,14 +61,29 @@ function DayIncomeExpenseInfos() {
},
];

const eventHandler = (item: AccountsData) => {
const [searchResultData] = useRecoilState(searchResultDataAtom);
const [searchKeywordClicked] = useRecoilState(searchKeywordClickedState);

const eventHandler = (item: AccountsData | GetSearchItem) => {
console.log("item: ", item);
};

return (
<ul>
{exampleAccounts === undefined ? (
<div>Nothing!</div>
<DayIncomeExpenseInfosUI.ContainerUl>
{searchKeywordClicked && searchResultData.length > 0 ? (
searchResultData.map(item => (
<DayIncomeExpenseInfo
key={item.accountId}
onClick={() => eventHandler(item)}
item={item}
/>
))
) : searchKeywordClicked && searchResultData.length === 0 ? (
<DayIncomeExpenseInfosUI.Nothing>
가계부 기록이 없습니다.
</DayIncomeExpenseInfosUI.Nothing>
) : exampleAccounts === undefined ? (
<div>가계부 기록이 없습니다.!</div>
) : (
exampleAccounts.map(item => (
<DayIncomeExpenseInfo
Expand All @@ -73,7 +93,7 @@ function DayIncomeExpenseInfos() {
/>
))
)}
</ul>
</DayIncomeExpenseInfosUI.ContainerUl>
);
}

Expand Down
20 changes: 20 additions & 0 deletions src/components/Common/DayIncomeExpenseInfos/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import styled from "@emotion/styled";

const ContainerUl = styled.ul`
width: 100%;
height: 100%;
overflow: auto;
`;

const Nothing = styled.div`
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, 50%);
display: flex;
justify-content: center;
align-itmes: center;
font-size: 13px;
`;

export const DayIncomeExpenseInfosUI = { ContainerUl, Nothing } as const;
70 changes: 60 additions & 10 deletions src/components/SearchInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,85 @@
import SearchSVG from "@/public/icon/Search.svg";
import CancleSVG from "@/public/icon/Cancle.svg";
import { SearchInputUI } from "./style";
import { ChangeEvent, useState } from "react";
import { ChangeEvent, useEffect, useState } from "react";
import { AccountBookAPI } from "@/src/core/api/accountBook";
import { useRecoilState } from "recoil";
import {
autoCompleteAtom,
getSearchAtom,
} from "@/src/hooks/recoil/useGetSearch";
import { autoCompleteDatasAtom } from "@/src/hooks/recoil/autoCompleteResults";
import { showKeywordResultsaAtom } from "@/src/hooks/recoil/showKeywordResultsState";

function SearchInput() {
const [showCancleButton, setShowCancleButton] = useState<boolean>(false);
const [keyword, setKeyword] = useState<string>("");

const handleFocus = () => {
setShowCancleButton(true);
};
const [autoKeyword, setAutoKeyword] = useRecoilState(autoCompleteAtom);
const [, setAutoCompleteDatas] = useRecoilState(autoCompleteDatasAtom);
const [, setShowKeywordResults] = useRecoilState(showKeywordResultsaAtom);
const [getSearchParams, setGetSearchParams] = useRecoilState(getSearchAtom);

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.value;
const newValue = e.target.value;
console.log("new value: ", newValue);
setKeyword(newValue);

setAutoKeyword(prev => ({
...prev,
query: newValue,
}));

if (autoKeyword.query.length >= 0) {
setShowCancleButton(true);
} else if (autoKeyword.query.length <= 0) {
setShowCancleButton(false);
}
};

const handleCancleButtonClick = () => {
setKeyword("");
setAutoKeyword(prev => ({
...prev,
query: "",
}));
setGetSearchParams(prev => ({
...prev,
categoryName: "",
}));
};

useEffect(() => {
const debounce = setTimeout(() => {
const getAutoCompleteDatas = async () => {
try {
const response = await AccountBookAPI.getAutocomplete(
autoKeyword.limit,
autoKeyword.query
);
if (response.status === 200) {
console.log("자동완성 검색 성공: ", response.data);
setAutoCompleteDatas(response.data);
setShowKeywordResults(true);
}
} catch (error) {
console.log("자동완성 검색 실패: ", error);
}
};

if (autoKeyword.query.length > 0) getAutoCompleteDatas();
}, 200);

return () => {
clearTimeout(debounce);
};
}, [autoKeyword.query, setAutoCompleteDatas]);

return (
<SearchInputUI.Container>
<SearchInputUI.Wrapper>
<img src={SearchSVG} alt="돋보기" />
<SearchInputUI.Input
type="search"
value={autoKeyword.query}
placeholder="검색어 입력"
value={keyword}
onFocus={handleFocus}
onChange={handleChange}
/>
{showCancleButton && (
Expand Down
73 changes: 73 additions & 0 deletions src/components/SearchKeywordResults/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useRecoilState } from "recoil";
import { SearchKeywordResultsUI } from "./style";
import {
autoCompleteAtom,
getSearchAtom,
} from "@/src/hooks/recoil/useGetSearch";
import { autoCompleteDatasAtom } from "@/src/hooks/recoil/autoCompleteResults";
import { AccountBookAPI } from "@/src/core/api/accountBook";
import { useEffect } from "react";
import { searchResultDataAtom } from "@/src/hooks/recoil/searchResultData";
import { showKeywordResultsaAtom } from "@/src/hooks/recoil/showKeywordResultsState";
import { searchKeywordClickedState } from "@/src/hooks/recoil/searchKeywordClickedState";

function SearchKeywordResults() {
const [getSearchParams, setGetSearchParams] = useRecoilState(getSearchAtom);
const [autoKeyword] = useRecoilState(autoCompleteAtom);
const [autoCompleteDatas] = useRecoilState(autoCompleteDatasAtom);
const [, setSearchResultData] = useRecoilState(searchResultDataAtom);
const [showKeywordResults, setShowKeywordResults] = useRecoilState(
showKeywordResultsaAtom
);
const [, setSearchKeywordClicked] = useRecoilState(searchKeywordClickedState);

const handleKeywordClick = (item: string) => {
setGetSearchParams(prev => ({
...prev,
categoryName: item,
}));
setSearchKeywordClicked(true);
setShowKeywordResults(false);
};

useEffect(() => {
const serachData = async () => {
try {
const response = await AccountBookAPI.getSearch(
getSearchParams.categoryName
);
if (response.status === 200) {
console.log("검색 성공: ", response.data);
setSearchResultData(response.data);
}
} catch (error) {
console.log("getSearch Error: ", error);
}
};

serachData();
}, [getSearchParams.categoryName]);

return (
<>
{autoKeyword.query.length > 0 &&
autoCompleteDatas &&
showKeywordResults && (
<SearchKeywordResultsUI.ContainerUl>
{autoCompleteDatas.map((item, index) => (
<li key={index} onClick={() => handleKeywordClick(item)}>
<SearchKeywordResultsUI.Name>
{item}
</SearchKeywordResultsUI.Name>
<SearchKeywordResultsUI.Badge>
카테고리
</SearchKeywordResultsUI.Badge>
</li>
))}
</SearchKeywordResultsUI.ContainerUl>
)}
</>
);
}

export default SearchKeywordResults;
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { theme } from "@/src/assets/theme";

const containerWidth = "100% - 40px";

const ContainerUl = styled.div`
const ContainerUl = styled.ul`
width: calc(${containerWidth});
max-height: 350px;
${theme.border_radius};
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
background-color: ${theme.font_color.white};
overflow: auto;

position: absolute;
top: 140px; // 77(hearder)+46+17
Expand All @@ -16,18 +18,18 @@ const ContainerUl = styled.div`

li {
height: 50px;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;

// &:hover {
// background-color: rgba(25, 118, 210, 0.04);
// }
&:hover {
background-color: rgba(25, 118, 210, 0.04);

& > div:first-of-type {
height: inherit;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
& > div:first-of-type {
font-weight: bold;
}
}
}
`;
Expand All @@ -49,4 +51,4 @@ const Badge = styled.div`
align-items: center;
`;

export const SearchListsUI = { ContainerUl, Name, Badge } as const;
export const SearchKeywordResultsUI = { ContainerUl, Name, Badge } as const;
16 changes: 0 additions & 16 deletions src/components/SearchLists/index.tsx

This file was deleted.

5 changes: 3 additions & 2 deletions src/components/SearchResults/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import DayIncomeExpenseInfos from "../Common/DayIncomeExpenseInfos";
import { SearchResultsUI } from "./style";

function SearchResults() {
return (
<div>
<SearchResultsUI.Container>
<DayIncomeExpenseInfos />
</div>
</SearchResultsUI.Container>
);
}

Expand Down
11 changes: 9 additions & 2 deletions src/components/SearchResults/style.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import styled from "@emotion/styled";
import { theme } from "@/src/assets/theme";
import { HeaderHeight, NavigationItemsHeight } from "@/src/assets/height";

export const SearchResultsUI = {} as const;
const searchResutlsHeight = `100% - ${HeaderHeight}px - 80px - ${NavigationItemsHeight}px`;

const Container = styled.div`
width: 100%;
height: calc(${searchResutlsHeight});
`;

export const SearchResultsUI = { Container } as const;
Loading