Skip to content

Commit

Permalink
Merge pull request #67 from onetuks/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
onetuks authored Sep 15, 2024
2 parents c0e4ac1 + a7fdd57 commit 7f298e5
Show file tree
Hide file tree
Showing 21 changed files with 1,395 additions and 43 deletions.
59 changes: 45 additions & 14 deletions src/api/AdminBookApis.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,77 @@
import { BookResponse } from "@/api/BookApis";
import { Book, BookResponse, BookResponses } from "@/api/BookApis";

Check warning on line 1 in src/api/AdminBookApis.ts

View workflow job for this annotation

GitHub Actions / deploy

'Book' is defined but never used
import { CategoryType } from "@/types/Category";
import { get, patchFormData, remove } from "@/api/ServerRequest";
import { buildPageQuery } from "@/types/Page";
import {
buildPageQuery,

Check warning on line 5 in src/api/AdminBookApis.ts

View workflow job for this annotation

GitHub Actions / deploy

'buildPageQuery' is defined but never used
buildPageQueryWithOutQuestionMark,
Page,
} from "@/types/Page";

export interface BookPatchRequest {
title: string;
authorName: string;
introduction: string;
isbn: string;
publisher: string;
introduction: string | null;
isbn: string | null;
publisher: string | null;
categories: CategoryType[];
isIndie: boolean;
isPermitted: boolean;
coverImageFilename: string | null;
}

export const AdminBookApis = {
URI_PREFIX: "/admin/books",
patchBook: async (
bookId: number,
request: BookPatchRequest,
coverImage: File
coverImage: File | null
): Promise<BookResponse> => {
// 도서 정보 수정
return await patchFormData(`/admin/books/${bookId}`, request, [
"cover-image",
coverImage,
]).then((data) => data as BookResponse);
return await patchFormData(
`${AdminBookApis.URI_PREFIX}/${bookId}`,
request,
["cover-image", coverImage]
)
.then((data) => data as BookResponse)
.catch((error) => {
throw error;
});
},
deleteBook: async (bookId: number): Promise<void> => {
// 도서 삭제
remove(`/admin/books/${bookId}`);
remove(`/admin/books/${bookId}`).catch((error) => {
throw error;
});
},
getBooksForInspection: async (
inspectionMode: boolean,
page?: number,
size?: number
): Promise<BookResponse[]> => {
): Promise<Page<BookResponse>> => {
// 검수 대상 도서 다건 조회
return await get(
`/admin/books?inspection-mode=${inspectionMode}${buildPageQuery(
`/admin/books?inspection-mode=${inspectionMode}${buildPageQueryWithOutQuestionMark(
page,
size
)}`
).then((data) => data as BookResponse[]);
)
.then((data) => (data as BookResponses).responses)
.catch((error) => {
throw error;
});
},
};

export const initBookPatchRequest = (): BookPatchRequest => {
return {
title: "",
authorName: "",
introduction: null,
isbn: null,
publisher: null,
categories: [],
isIndie: true,
isPermitted: true,
coverImageFilename: null,
};
};
56 changes: 38 additions & 18 deletions src/components/bar/PaginationBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,43 @@ const props = defineProps<{
pageInfo: Page<object>;
}>();
const page = ref<Page<object>>({ ...props.pageInfo });
const pageNumbers = ref<number[]>([]);
const emits = defineEmits<{
(event: "request:Page", pageNumber: number): void;
}>();
watch(
() => props.pageInfo,
(newPage) => {
page.value = newPage;
selectPage(page.value.number);
(newPageInfo) => {
page.value = { ...newPageInfo };
pageNumbers.value = getPageNumbers(page.value.number);
}
);
const selectPage = (index: number): void => {
page.value.number = index;
pageNumbers.value = getPageNumbers(index);
const page = ref<Page<object>>({ ...props.pageInfo });
const pageNumbers = ref<number[]>([]);
const selectPage = (pageNumber: number): void => {
if (
pageNumber < pageNumbers.value[0] ||
pageNumber > pageNumbers.value[pageNumbers.value.length - 1]
) {
return;
}
page.value.number = pageNumber - 1;
pageNumbers.value = getPageNumbers(pageNumber);
emits("request:Page", pageNumber);
};
const getPageNumbers = (index: number): number[] => {
const getPageNumbers = (pageNumber: number): number[] => {
const numbers = [];
const start = Math.max(
1,
Math.min(index - 2, page.value.totalPages - PAGE_LIMIT + 1)
Math.min(pageNumber - 2, page.value.totalPages - PAGE_LIMIT + 1)
);
const end = Math.min(
page.value.totalPages,
Math.max(index + 2, start + PAGE_LIMIT - 1)
Math.max(pageNumber + 2, start + PAGE_LIMIT - 1)
);
for (let i = start; i <= end; i++) {
numbers.push(i);
Expand All @@ -43,20 +55,28 @@ selectPage(page.value.number);

<template>
<div v-if="pageNumbers.length > 0" class="pagination-container">
<img alt="prev-page" src="@/assets/icon/direction/left_icon.png" />
<img
alt="prev-page"
src="@/assets/icon/direction/left_icon.png"
@click="selectPage(page.number - 1)"
/>
<div class="pagination-numbers-container">
<div
v-for="index in pageNumbers"
:key="index"
v-for="pageNumber in pageNumbers"
:key="pageNumber"
class="pagination"
@click="selectPage(index)"
@click="selectPage(pageNumber)"
>
<span :class="['page', { active: index === page.number + 1 }]">
{{ index }}
<span :class="['page', { active: pageNumber === page.number + 1 }]">
{{ pageNumber }}
</span>
</div>
</div>
<img alt="prev-page" src="@/assets/icon/direction/right_icon.png" />
<img
alt="prev-page"
src="@/assets/icon/direction/right_icon.png"
@click="selectPage(page.number + 1)"
/>
</div>
</template>

Expand Down
110 changes: 110 additions & 0 deletions src/pages/admin/book/list/AdminBookListPage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<script setup lang="ts">
import { Book } from "@/api/BookApis";
import { emptyPage, Page } from "@/types/Page";
import { AdminBookApis } from "@/api/AdminBookApis";
import { ref } from "vue";
import PaginationBar from "@/components/bar/PaginationBar.vue";
import router from "@/router";
const books = ref<Page<Book>>(emptyPage());
const moveToAdminBookModificationPage = (bookId: number): void => {
router.push(`/admin/books/${bookId}/modification`);
};
const removeBook = async (bookId: number): Promise<void> => {
await AdminBookApis.deleteBook(bookId)
.then(() => alert("도서가 성공적으로 삭제되었습니다."))
.catch((error) => console.error("AdminHomePage.removeBook", error));
};
const fetchBooksForInspection = async (page: number): Promise<void> => {
await AdminBookApis.getBooksForInspection(true, page)
.then((response) => {
console.log(response);
books.value = { ...response } as Page<Book>;
})
.catch((error) =>
console.error("AdminHomePage.fetchBooksForInspection", error)
);
};
</script>

<template>
<div class="admin-book-list-page-container">
<table class="admin-book-list-page-table">
<tr>
<th>제목</th>
<th>ISBN</th>
<th>수정/삭제</th>
</tr>
<tbody>
<tr v-for="(book, index) in books.content" :key="index">
<td class="admin-book-list-page-title">{{ book.title }}</td>
<td class="admin-book-list-page-isbn">
{{ book.isbn ? book.isbn : "NaN" }}
</td>
<td class="admin-book-list-page-button-container">
<div
class="admin-book-list-page-button"
v-if="book.bookId"
@click="moveToAdminBookModificationPage(book.bookId)"
>
수정
</div>
<div
class="admin-book-list-page-button"
v-if="book.bookId"
@click="removeBook(book.bookId)"
>
삭제
</div>
</td>
</tr>
</tbody>
</table>
<PaginationBar :page-info="books" @request:Page="fetchBooksForInspection" />
</div>
</template>

<style scoped>
.admin-book-list-page-container {
padding: 13px 15px;
width: 100%;
}
.admin-book-list-page-table {
width: 100%;
}
.admin-book-list-page-table th,
.admin-book-list-page-table td {
border-bottom: 1px solid var(--border-primary);
height: 50px;
}
.admin-book-list-page-title {
width: 50%;
}
.admin-book-list-page-isbn {
width: 20%;
}
.admin-book-list-page-button-container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.admin-book-list-page-button {
border: 1px solid var(--button-primary);
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
padding: 5px;
margin-left: 5px;
}
</style>
Loading

0 comments on commit 7f298e5

Please sign in to comment.