Mission:

Reviewing API request and implement sending API request with axios or fetch

1. Implementing the class

// In JS, the class recommended in seperate js files.
//JS에서는 클래스를 각각 다른 파일에 저장해서 사용하길 권장한다.
//따라서 Product.js, ElectronicProduct.js를 만들어서 각 파일에
// 각 클래스를 옮겨왔다.
export class Product{
  constructor(name, description, price, tags, images, favoriteCount){
    this.name= name;
    this.description=description;
    this.price= price;
    this.tags=tags;
    this.images=images;
    this.favoriteCount=favoriteCount;
  }

  /**Conditions:
   * Product class has the method 'favorite'.
   * When the favorite is called, the number of 'liked' increases by 1
   * Product 클래스는 favorite 메소드를 가집니다. 
   * favorite 메소드가 호출될 경우 찜하기 수가 1 증가합니다.
   */
  // favorite이라는 이름을 가진 method 정의
  /**  매개변수가 필요할까? Will the parameter needed?
   * No.. Click 이벤트 핸들링은 필요할 거 같은데, 원시 자료형 매개변수가 필요한지는 모르겠음
   * I think the eventhandling is needed in favorite method,
   * but I'm not sure about the primitive data types.
   * -> No parameter, just put a formula.
  */ 
  favorite(){
    let liked = this.favoriteCount + 1;
    return liked;
  }
}
// In JS, the class recommended in seperate js files.
//JS에서는 클래스를 각각 다른 파일에 저장해서 사용하길 권장한다.
/* 18:40 각기 다른 파일에서 클래스 상속하려면 export & import 필수라고 한다.
 * 따라서 export & import 사용
 * I was curious about if the inheritance in different files available,
 * I searched on the internet.
 * It said I must need export and import, 
 * so I add those code in Product.js and E-Product.js.
 * <https://stackoverflow.com/questions/59325349/how-can-i-inherit-a-js-class-from-another-js-class-which-are-separate-files>
 */
import { Product } from "./Product";
/** Conditions:
 * ElectronicProduct 클래스는 Product를 상속하며, 
 * 추가로 manufacturer(제조사) 프로퍼티를 가집니다. 
 * The class ElectronicProduct inherit class Product,
 * and has a manufacturer property. */
class ElectronicProducts extends Product {
  constructor(
    name, description, price, tags, images, favoriteCount, manufacturer
  ){
    //ElectronicProducts class가 Product class를 상속했고 
    //추가 프로퍼티 manufacturer가 있기 때문에
    //super를 통해 부모 생성자를 호출하는 과정이 필요하다.
    // Since the ElectronicProducts class inheritants Product,
    // and it has new property named 'manufacturer',
    // this class should call the parents constructor with super().
    super(name, description, price, tags, images, favoriteCount);
    this.manufacturer=manufacturer;
  }
}
// In JS, the class recommended in seperate js files.
//JS에서는 클래스를 각각 다른 파일에 저장해서 사용하길 권장한다.
/* Conditions:
class 키워드를 이용해서 Article 클래스를 만들어 주세요.
Article 클래스는 title(제목), content(내용), writer(작성자), likeCount(좋아요 수) 프로퍼티를 가집니다.
Article 클래스는 like method를 가집니다. like 메소드가 호출될 경우 좋아요 수가 1 증가합니다.
*/
class Article{
  constructor(title, content, writer, likeCount){
    this.title=title;
    this.content=content;
    this.writer=writer;
    this.likeCount=likeCount;
  }
  like(){
    let addLike = this.likeCount +1;
    return addLike;
  }
}

2. Impletmenting API request function

//ArticleService.js
import axios from "axios";

const instance = axios.create({
  // baseURL: '<https://panda-market-api-crud.vercel.app/docs/>',
  // -1- 
  baseURL: '<https://panda-market-api-crud.vercel.app>',
  timeout: 5000
  //timeout: xnnn = x초 내에 연결이 되지 않으면 error return
});

/* The swagger url looks like this,
<https://panda-market-api-crud.vercel.app/docs/#/Article/CreateArticle>
I was confused from where I should use the endpoint.
`/#/Article/ListArticles` vs `/Article/ListArticles`
So I asked to gemini and got an answer.
Then revise codes with no-# endpoints.
<https://g.co/gemini/share/6b23700fe84e>
 */
// export async function getArticleList(queryParams= {page, pageSize, keyword}) {
//   const res = await instance.get(`/Article/ListArticles`, {
//     params: queryParams
//   });
//   return res.data;
// }
// -2-
export async function getArticleList({ page, pageSize, keyword }) {
  const res = await instance.get(`/articles`, {
    params: { page, pageSize, keyword }
  });
  return res.data;
} 

// export async function getArticle(){
//   const res = await instance.get(`/Article/ListArticles`);
//   return res.data;
// }
//-2- & -3-
export async function getArticle(articleId){
  // const res = await instance.get(`/articles/${articleId}`, articleId);
  const res = await instance.get(`/articles/${articleId}`);
  return res.data;
}

export async function createArticle({title, content, image}) {
  const params = { title, content, image };

  // const res = await instance.post(`/Article/CreateArticle`, surveyData);
  const res = await instance.get(`/articles`, {
    params: params
  });
  return res.data;
}

// export async function patchArticle(articleId) {
//   const res = await instance.patch(`/articles/${articleId}`, articleId);
//   return res.data;  
// }
//-4-
export async function patchArticle(articleId, updateData) {
  const res = await instance.patch(`/articles/${articleId}`, updateData);
  return res.data;  
}

export async function deleteArticle(articleId) {
  const res = await instance.delete(`/articles/${articleId}`);
  return res.data;  
}
// TODO: .then() 메소드를 이용해 비동기 처리를 해주세요
// .catch()를 이용해 오류 처리를 해주세요

-1- As the condition saids using `https://panda-market-api-crud.vercel.app/docs', I was typing same url first, but it didn't worked.

스크린샷 2025-09-26 오후 9.44.57.png

Then I asked to gemini what did I missed.

It replied I should use https://...vercel.app not the /docs included one.

So I changed the endpoint and it connected with API.

스크린샷 2025-09-26 오후 9.50.09.png

But it returned 404 error.

Therefore, I checked the JSON data of ‘https://…vercel.app/articles’ and it looks like this.

{"list":[
{
"id":4494,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:12:18.953Z",
"updatedAt":"2025-09-26T08:12:18.953Z"
},
{
"id":4493,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:12:15.844Z",
"updatedAt":"2025-09-26T08:12:15.844Z"
},
{
"id":4492,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다...",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:07:01.632Z",
"updatedAt":"2025-09-26T08:07:01.632Z"
},
{
"id":4491,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:06:58.738Z",
"updatedAt":"2025-09-26T08:06:58.738Z"
},
{
"id":4490,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:06:18.107Z",
"updatedAt":"2025-09-26T08:06:18.107Z"
},
{
"id":4489,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:06:10.834Z",
"updatedAt":"2025-09-26T08:06:10.834Z"
},
{
"id":4488,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:06:04.307Z",
"updatedAt":"2025-09-26T08:06:04.307Z"
},
{
"id":4487,"title":"게시글 제목입니다....",
"content":"게시글 내용입니다.....",
"image":"<https://example.com/>...",
"createdAt":"2025-09-26T08:06:02.621Z",
"updatedAt":"2025-09-26T08:06:02.621Z"
},
{
"id":4485,"title":"제목테스트",
"content":"내용테스트",
"image":"<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/A_Panda_eating.jpg/250px-A_Panda_eating.jpg>",
"createdAt":"2025-09-23T05:19:52.782Z","updatedAt":"2025-09-23T05:19:52.782Z"
},
{
"id":4480,"title":"게시글 제목입니다.",
"content":"게시글 내용입니다.",
"image":"<https://cdn.pixabay.com/photo/2025/04/24/22/36/beach-9556784_1280.jpg>",
"createdAt":"2025-09-15T08:14:29.220Z",
"updatedAt":"2025-09-15T08:14:29.220Z"
}],
"totalCount":2901
}

Following inspecting these datas, I found some arguments were wrong in my codes in main.js.