Skip to content

Commit

Permalink
Merge pull request #745 from soma0078/React-이송아-sprint11
Browse files Browse the repository at this point in the history
[이송아] sprint11
  • Loading branch information
jyh0521 authored Jul 22, 2024
2 parents 8f55f08 + bffa383 commit a663e23
Show file tree
Hide file tree
Showing 35 changed files with 10,519 additions and 231 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# production
/build
.next

# misc
.DS_Store
Expand Down
11 changes: 6 additions & 5 deletions package-lock.json

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

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "1-weekly-mission",
"version": "0.1.0",
"private": true,
"module": "module",
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
Expand All @@ -12,6 +13,7 @@
"pretendard": "^1.3.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.52.1",
"react-icons": "^5.0.1",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
Expand Down Expand Up @@ -39,6 +41,9 @@
]
},
"devDependencies": {
"typescript": "^5.4.5"
"autoprefixer": "^10.4.19",
"postcss": "^8.4.39",
"tailwindcss": "^3.4.6",
"typescript": "5.0"
}
}
6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import AddItemPage from './pages/AddItemPage/AddItemPage';
import CommunityFeedPage from './pages/CommunityFeedPage/CommunityFeedPage';
import Header from './components/Layout/Header';
import ItemPage from './pages/ItemPage/ItemPage';
import './index.css';

function App() {
return (
Expand Down
46 changes: 5 additions & 41 deletions src/api/itemApi.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,5 @@
interface Entity {
id: string;
name: string;
}

interface Product extends Entity {
price: number;
}

interface ProductDetail extends Entity {
description: string;
}

interface Comment extends Entity {
productId: string;
content: string;
}

interface ProductResponse {
list: Product[];
totalCount: number;
}

export async function getProducts(params: {
orderBy: string;
page: number;
pageSize: number;
}): Promise<ProductResponse> {
const query = new URLSearchParams({
orderBy: params.orderBy,
page: params.page.toString(),
pageSize: params.pageSize.toString(),
}).toString();
export async function getProducts(params = {}) {
const query = new URLSearchParams(params).toString();

try {
const response = await fetch(`https://panda-market-api.vercel.app/products?${query}`);
Expand All @@ -45,7 +14,7 @@ export async function getProducts(params: {
}
}

export async function getProductDetail(productId: string): Promise<ProductDetail> {
export async function getProductDetail(productId: number) {
if (!productId) {
throw new Error('Invalid product ID');
}
Expand All @@ -63,18 +32,13 @@ export async function getProductDetail(productId: string): Promise<ProductDetail
}
}

export async function getProductComments(params: {
productId: string;
params?: Record<string, any>;
}): Promise<Comment[]> {
const { productId, params: queryParams } = params;

export async function getProductComments({ productId, params }: { productId: number; params: {} }) {
if (!productId) {
throw new Error('Invalid product ID');
}

try {
const query = new URLSearchParams(queryParams).toString();
const query = new URLSearchParams(params).toString();
const response = await fetch(`https://panda-market-api.vercel.app/products/${productId}/comments?${query}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
Expand Down
10 changes: 10 additions & 0 deletions src/assets/images/icons/icon_google.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/assets/images/icons/icon_kakao.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import Logo from '../../assets/images/logo/logo.svg';
import { Link, NavLink, useLocation } from 'react-router-dom';
import './Header.css';
Expand All @@ -11,6 +10,8 @@ function getLinkStyle({ isActive }: { isActive: boolean }) {
function Header() {
const location = useLocation(); // 현재 경로 정보

if (window.location.pathname === '/login') return null;

return (
<header className="globalHeader">
<div className="headerLeft">
Expand Down
5 changes: 2 additions & 3 deletions src/components/UI/DeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react';
import styled from 'styled-components';
import { ReactComponent as CloseIcon } from '../../assets/images/icons/ic_x.svg';

interface DeleteButtonProps {
type DeleteButtonProps = {
onClick: () => void;
label: string;
}
};

const Button = styled.button`
background-color: ${({ theme }) => theme.colors.gray[400]};
Expand Down
8 changes: 4 additions & 4 deletions src/components/UI/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useState } from 'react';
import { useState } from 'react';
import './DropdownMenu.css';
import { ReactComponent as SortIcon } from '../../assets/images/icons/ic_sort.svg';

interface DropdownMenuProps {
onSortSelection: (value: string) => void;
}
type DropdownMenuProps = {
onSortSelection: (value: 'recent' | 'favorite') => void;
};

function DropdownMenu({ onSortSelection }: DropdownMenuProps) {
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
Expand Down
4 changes: 2 additions & 2 deletions src/components/UI/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react';
import styled from 'styled-components';

interface IconProps {
type IconProps = {
iconComponent: React.ComponentType<React.SVGProps<SVGSVGElement>>;
size?: number;
fillColor?: string;
outlineColor?: string;
}
};

const IconWrapper = styled.div<{
$size?: number;
Expand Down
7 changes: 3 additions & 4 deletions src/components/UI/PaginationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import React from 'react';
import './PaginationBar.css';
import { ReactComponent as LeftArrow } from '../../assets/images/icons/arrow_left.svg';
import { ReactComponent as RightArrow } from '../../assets/images/icons/arrow_right.svg';

interface PaginationBarProps {
type PaginationBarProps = {
totalPageNum: number;
activePageNum: number;
onPageChange: (pageNum: number) => void;
}
};

const PaginationBar = ({ totalPageNum, activePageNum, onPageChange }: PaginationBarProps) => {
const maxVisiblePages = 5;
let startPage: number = 1;
let startPage = 1;

if (totalPageNum <= maxVisiblePages) {
startPage = 1;
Expand Down
4 changes: 2 additions & 2 deletions src/components/UI/TagInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ const TagText = styled.span`
white-space: nowrap;
`;

interface TagInputProps {
type TagInputProps = {
tags: string[];
onAddTag: (tag: string) => void;
onRemoveTag: (tag: string) => void;
}
};

function TagInput({ tags, onAddTag, onRemoveTag }: TagInputProps) {
const [input, setInput] = useState<string>('');
Expand Down
7 changes: 7 additions & 0 deletions src/custom.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare module '*.svg' {
import React = require('react');

export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}
29 changes: 29 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
.btn {
@apply text-secondary-100 bg-primary-100 hover:bg-primary-200 active:bg-primary-200 rounded-full h-[56px] cursor-pointer;
}

.btn-disabled {
@apply bg-secondary-400 hover:bg-secondary-400 cursor-default;
}

.input {
@apply block bg-secondary-100 outline-none border border-secondary-100 focus:border-primary-100 font-normal w-full h-14 mt-4 inner-p rounded;
}

.input-error {
@apply border-error-red focus:border-error-red;
}

.inner-p {
@apply px-6 py-4;
}

.error-message {
@apply px-4 py-2 text-sm text-error-red font-semibold;
}
}
4 changes: 1 addition & 3 deletions src/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React from "react";

function HomePage() {
return <div>HomePage</div>;
return <div>홈페이지</div>;
}

export default HomePage;
19 changes: 11 additions & 8 deletions src/pages/ItemPage/ItemPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import styled from 'styled-components';
import { Container, LineDivider, StyledLink } from '../../styles/CommonStyles';
Expand All @@ -7,6 +7,7 @@ import ItemProfileSection from './components/ItemProfileSection';
import ItemCommentSection from './components/ItemCommentSection';
import { ReactComponent as BackIcon } from '../../assets/images/icons/ic_back.svg';
import LoadingSpinner from '../../components/UI/LoadingSpinner';
import { Product } from '../../types/ProductTypes';

const BackToMarketPageLink = styled(StyledLink)<{ $pill?: string }>`
display: flex;
Expand All @@ -18,23 +19,25 @@ const BackToMarketPageLink = styled(StyledLink)<{ $pill?: string }>`
`;

function ItemPage() {
const [product, setProduct] = useState(null);
const [product, setProduct] = useState<Product | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string>('');
const [error, setError] = useState<string | null>(null);

const { productId } = useParams<{ productId: string }>();
const { productId } = useParams();

const productIdNumber = Number(productId);

useEffect(() => {
async function fetchProduct() {
if (!productId) {
if (!productIdNumber) {
setError('상품 아이디가 제공되지 않았어요.' || '');
setIsLoading(false);
return;
}

setIsLoading(true);
try {
const data = await getProductDetail(productId);
const data: Product = await getProductDetail(productIdNumber);
if (!data) {
throw new Error('해당 상품의 데이터를 찾을 수 없습니다.');
}
Expand All @@ -47,7 +50,7 @@ function ItemPage() {
}

fetchProduct();
}, [productId]);
}, [productIdNumber]);

if (error) {
alert(`오류: ${error}`);
Expand All @@ -64,7 +67,7 @@ function ItemPage() {

<LineDivider />

<ItemCommentSection productId={productId} />
<ItemCommentSection productId={productIdNumber} />

<BackToMarketPageLink $pill="true" to="/items">
목록으로 돌아가기
Expand Down
Loading

0 comments on commit a663e23

Please sign in to comment.