Skip to content

Commit c6aa9e6

Browse files
committed
feat. 상품목록 - 에러상태에 대한 로직추가
1 parent ca66546 commit c6aa9e6

4 files changed

Lines changed: 61 additions & 30 deletions

File tree

.github/pull_request_template.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@
1616

1717
**상품 목록 로딩**
1818

19-
- [ ] 페이지 접속 시 로딩 상태가 표시된다
20-
- [ ] 데이터 로드 완료 후 상품 목록이 렌더링된다
21-
- [ ] 로딩 실패 시 에러 상태가 표시된다
22-
- [ ] 에러 발생 시 재시도 버튼이 제공된다
19+
- [X] 페이지 접속 시 로딩 상태가 표시된다
20+
- [X] 데이터 로드 완료 후 상품 목록이 렌더링된다
21+
- [X] 로딩 실패 시 에러 상태가 표시된다
22+
- [X] 에러 발생 시 재시도 버튼이 제공된다
2323

2424
**상품 목록 조회**
2525

26-
- [ ] 각 상품의 기본 정보(이미지, 상품명, 가격)가 카드 형태로 표시된다
26+
- [X] 각 상품의 기본 정보(이미지, 상품명, 가격)가 카드 형태로 표시된다
2727

2828
**한 페이지에 보여질 상품 수 선택**
2929

30-
- [ ] 드롭다운에서 10, 20, 50, 100개 중 선택할 수 있으며 기본 값은 20개 이다.
31-
- [ ] 선택 변경 시 즉시 목록에 반영된다
30+
- [X] 드롭다운에서 10, 20, 50, 100개 중 선택할 수 있으며 기본 값은 20개 이다.
31+
- [X] 선택 변경 시 즉시 목록에 반영된다
3232

3333
**상품 정렬 기능**
3434

@@ -71,7 +71,7 @@
7171

7272
**현재 상품 수 표시**
7373

74-
- [ ] 현재 조건에서 조회된 총 상품 수가 화면에 표시된다
74+
- [X] 현재 조건에서 조회된 총 상품 수가 화면에 표시된다
7575
- [ ] 검색이나 필터 적용 시 상품 수가 실시간으로 업데이트된다
7676

7777
#### 장바구니

src/domains/product/components/ProductList/ProductItem.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable max-len */
12
import { component, html } from "../../../../core/component";
23
import { Product } from "../../../../types";
34

src/main.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ const enableMocking = () =>
1818
*/
1919
function main() {
2020
render`
21-
<div class="min-h-screen bg-gray-50">
21+
<div class="bg-gray-50 flex flex-col flex-grow h-screen">
2222
${TopBar()}
23-
${ProductListPage()}
23+
<div class="flex-1">
24+
${ProductListPage()}
25+
</div>
2426
${Footer()}
2527
</div>
2628
`;

src/pages/product/list.ts

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,64 @@ import { useState } from "../../core/state/useState";
55
import { ProductFilter } from "../../domains/product/components/ProductList/ProductFilter";
66
import { ProductList } from "../../domains/product/components/ProductList/ProductList";
77
import { Product } from "../../types";
8+
import { on } from "../../core/on";
89

910
export const ProductListPage = component(() => {
1011
const $products = useState<Product[]>([]);
1112
const $isLoading = useState(true);
1213
const $itemsPerPage = useState(20);
14+
const $error = useState<string | null>(null);
15+
16+
const fetchProducts = async () => {
17+
try {
18+
$isLoading.set(true);
19+
$error.set(null);
20+
21+
// throw new Error("테스트 에러입니다!");
22+
23+
const response = await getProducts({
24+
page: 1,
25+
limit: $itemsPerPage.get(),
26+
sort: "price_asc",
27+
});
28+
29+
$products.set(response.products);
30+
$isLoading.set(false);
31+
} catch (error) {
32+
console.log("상품 로딩 실패: ", error);
33+
34+
$error.set(error instanceof Error ? error.message : "상품을 불러오는데 실패했습니다.");
35+
$isLoading.set(false);
36+
}
37+
};
1338

1439
useEffect(() => {
15-
(async () => {
16-
try {
17-
const response = await getProducts({
18-
page: 1,
19-
limit: $itemsPerPage.get(),
20-
sort: "price_asc",
21-
});
22-
23-
$products.set(response.products);
24-
$isLoading.set(false);
25-
} catch (error) {
26-
console.log("상품 로딩 실패: ", error);
27-
$isLoading.set(false);
28-
}
29-
})();
40+
fetchProducts();
3041
}, [$itemsPerPage]);
3142

3243
return html`
33-
<main class="max-w-md mx-auto px-4 py-4">
34-
<!-- 검색 및 필터 -->
35-
${ProductFilter({ $itemsPerPage })}
36-
<!-- 상품 목록 -->
37-
${ProductList({ $products, $isLoading, $itemsPerPage })}
44+
<main class="h-full max-w-md mx-auto px-4 py-4">
45+
${$error.ref((error) => {
46+
if (error) {
47+
return html` <div class="h-full w-full flex flex-col gap-4 items-center justify-center text-center font-bold">
48+
<p class="font-medium">${$error}</p>
49+
<button
50+
class="bg-blue-500 p-3 rounded-md flex-shrink-0 text-white hover:text-gray-200"
51+
${on("click", () => {
52+
fetchProducts();
53+
})}
54+
>
55+
다시 시도
56+
</button>
57+
</div>`;
58+
}
59+
return html`
60+
<!-- 검색 및 필터 -->
61+
${ProductFilter({ $itemsPerPage })}
62+
<!-- 상품 목록 -->
63+
${ProductList({ $products, $isLoading, $itemsPerPage })}
64+
`;
65+
})}
3866
</main>
3967
`;
4068
});

0 commit comments

Comments
 (0)