Skip to content
Merged
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
52 changes: 29 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"axios": "^1.7.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.26.2",
"react-scripts": "5.0.1",
"typescript": "^5.6.3",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions src/@types/global/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
declare module '*.png';
declare module '*.svg';
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import ItemCard from './ItemCard';
import '../style/Items.css';
import { ReactComponent as SearchIcon } from '../images/ic_search.svg';
import { Link, useNavigate } from 'react-router-dom';
import {
Product,
ProductListResponse,
ProductOrderBy,
} from './types/productTypes';

const getPageSize = () => {
const width = window.innerWidth;
Expand All @@ -20,17 +25,29 @@ const getPageSize = () => {
};

function AllItemsSection() {
const [orderBy, setOrderBy] = useState('recent');
const [orderBy, setOrderBy] = useState<ProductOrderBy>('recent');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

크으 굳굳 ! 타입을 확인해보니 "recent" | "favorite"군요 !

명확한 타입입니다 ! 굳굳 ~! 👍

const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(getPageSize());
const [itemList, setItemList] = useState([]);
const [itemList, setItemList] = useState<Product[]>([]);
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
const [totalPageNum, setTotalPageNum] = useState();
const [totalPageNum, setTotalPageNum] = useState(1);
const navigate = useNavigate();

const fetchSortedData = async ({ orderBy, page, pageSize }) => {
const fetchSortedData = async ({
orderBy,
page,
pageSize,
}: {
orderBy: ProductOrderBy;
page: number;
pageSize: number;
}) => {
try {
const products = await getProducts({ orderBy, page, pageSize });
const products: ProductListResponse = await getProducts({
orderBy,
page,
pageSize,
});
setItemList(products.list);
setTotalPageNum(Math.ceil(products.totalCount / pageSize));
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { useEffect, useState } from 'react';
import { getProducts } from '../api';
import ItemCard from './ItemCard';
import '../style/Items.css';
import {
Product,
ProductListResponse,
ProductOrderBy,
} from './types/productTypes';

const getPageSize = () => {
const width = window.innerWidth;
Expand All @@ -18,11 +23,20 @@ const getPageSize = () => {
};

function BestItemSection() {
const [itemList, setItemList] = useState([]);
const [itemList, setItemList] = useState<Product[]>([]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굳굳 ! 여러 곳에서 사용될 타입을 정의함으로서 재사용성을 높였군요 ! 👍👍

const [pageSize, setPageSize] = useState(getPageSize());

const fetchSortedData = async ({ orderBy, pageSize }) => {
const products = await getProducts({ orderBy, pageSize });
const fetchSortedData = async ({
orderBy,
pageSize,
}: {
orderBy: ProductOrderBy;
pageSize: number;
}) => {
const products: ProductListResponse = await getProducts({
orderBy,
pageSize,
});
setItemList(products.list);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import React, { useState } from 'react';
import { ReactComponent as Dropdown } from '../images/ic_kebab.svg';
import '../style/DropdownMenu.css';

function DropdownMenu({ onSelection }) {
interface DropdownMenuProps {
onSelection: (Option: string) => void;
}

function DropdownMenu({ onSelection }: DropdownMenuProps) {
const [isDropdownVisible, setIsDropdownVisible] = useState(false);

const toggleDropdown = () => {
Expand Down
22 changes: 16 additions & 6 deletions src/components/FileInput.js → src/components/FileInput.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { useEffect, useRef, useState } from 'react';
import { ChangeEvent, useEffect, useRef, useState } from 'react';
import '../style/ProductCreateForm.css';
import { ReactComponent as PlusIcon } from '../images/ic_plus.svg';
import { ReactComponent as DeleteIcon } from '../images/ic_X.svg';

function FileInput({ name, value, initialPreview, onChange }) {
interface FileInputProps {
name: string;
value: File | null;
initialPreview: string | null;
onChange: (name: string, value: File | null) => void;
}
Comment on lines +6 to +11
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

훌륭합니다. 😊 깔끔한 타입이예요.


function FileInput({ name, value, initialPreview, onChange }: FileInputProps) {
const [preview, setPreview] = useState(initialPreview);
const inputRef = useRef();
const inputRef = useRef<HTMLInputElement | null>(null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ref 타입도 명확하네요 ㅠㅠ

const [isImageValid, setIsImageValid] = useState(false);

const handleChange = (e) => {
const nextValue = e.target.files[0];
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수 이벤트 타입도 명확하구요 !

const fileList = e.target.files;
if (!fileList || fileList.length === 0) return;

const nextValue = fileList[0];
onChange(name, nextValue);
setIsImageValid(true);
};
Expand Down Expand Up @@ -55,7 +65,7 @@ function FileInput({ name, value, initialPreview, onChange }) {
<div className="preview-container">
<img
className="image-preview"
src={preview}
src={preview || ''}
alt="이미지 미리보기"
/>
<button className="image-delete-btn" onClick={handleClearClick}>
Expand Down
7 changes: 6 additions & 1 deletion src/components/ItemCard.js → src/components/ItemCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import React from 'react';
import '../style/Items.css';
import { ReactComponent as Heart } from '../images/ic_heart.svg';
import { Link } from 'react-router-dom';
import { Product } from './types/productTypes';

function ItemCard({ item }) {
interface ItemCardProps {
item: Product;
}

function ItemCard({ item }: ItemCardProps) {
return (
<Link to={`/items/${item.id}`} state={{ item: item }}>
<div className="itemCard">
Expand Down
41 changes: 30 additions & 11 deletions src/components/ItemComment.js → src/components/ItemComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,26 @@ import { ReactComponent as Profile } from '../images/ic_profile.svg';
import { ReactComponent as EmptyComment } from '../images/Img_inquiry_empty.svg';
import '../style/ItemComment.css';
import DropdownMenu from './DropdownMenu';
import { Product } from './types/productTypes';

function ItemComment({ item }) {
const [comments, setComments] = useState([]);
interface Comment {
id: number;
content: string;
writer: {
nickname: string;
image?: string;
};
updatedAt: string;
isEditing: boolean;
originalContent: string;
}

interface ItemCommentProps {
item: Product;
}

function ItemComment({ item }: ItemCommentProps) {
const [comments, setComments] = useState<Comment[]>([]);

useEffect(() => {
const fetchComments = async () => {
Expand All @@ -21,11 +38,13 @@ function ItemComment({ item }) {
);
console.log(response.data.list);
// 각 댓글에 isEditing 및 originalContent 상태 추가
const commentsWithEditState = response.data.list.map((comment) => ({
...comment,
isEditing: false,
originalContent: comment.content, // 원본 내용을 저장
}));
const commentsWithEditState: Comment[] = response.data.list.map(
(comment: Comment) => ({
...comment,
isEditing: false,
originalContent: comment.content, // 원본 내용을 저장
}),
);
setComments(commentsWithEditState);
} catch (error) {
console.error('Error fetching comments:', error);
Expand All @@ -35,7 +54,7 @@ function ItemComment({ item }) {
fetchComments();
}, []);

const formatDate = (isoDate) => {
const formatDate = (isoDate: string) => {
const date = new Date(isoDate);
return date
.toLocaleDateString('ko-KR', {
Expand All @@ -48,7 +67,7 @@ function ItemComment({ item }) {
};

// 수정하기 버튼 클릭 시: isEditing을 true로 하고 원본 content 저장
const handleEditClick = (index) => {
const handleEditClick = (index: number) => {
setComments((prevComments) =>
prevComments.map((comment, i) =>
i === index
Expand All @@ -59,7 +78,7 @@ function ItemComment({ item }) {
};

// 수정 취소 버튼 클릭 시: 원본 content로 복구
const handleCancelEdit = (index) => {
const handleCancelEdit = (index: number) => {
setComments((prevComments) =>
prevComments.map((comment, i) =>
i === index
Expand Down Expand Up @@ -92,7 +111,7 @@ function ItemComment({ item }) {
<>
<div className="comment-content">{comment.content}</div>
<DropdownMenu
onSelection={(action) => {
onSelection={(action: string) => {
if (action === 'fixed') {
handleEditClick(index);
}
Expand Down
File renamed without changes.
Loading
Loading