Skip to content

Commit

Permalink
feat: add management page (cont)
Browse files Browse the repository at this point in the history
  • Loading branch information
conganhhcmus committed Mar 13, 2024
1 parent 10935f3 commit fec5ef3
Show file tree
Hide file tree
Showing 14 changed files with 389 additions and 43 deletions.
14 changes: 12 additions & 2 deletions public/language/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,24 @@
"billing-management": "Quản lý thanh toán",
"role": "Quyền",
"email": "Email",
"edit-user": "Chỉnh sửa tài khoản",
"edit": "Chỉnh sửa",
"edit-user": "Sửa tài khoản",
"edit": "sửa",
"wallet": "",
"status": "Trạng Thái",
"username": "Tài Khoản",
"action": "Hành động",
"admin": "Admin",
"normal": "Normal",
"delete": "Xoá",
"add": "Thêm",
"add-comic": "Thêm truyện",
"edit-comic": "Sửa truyện",
"create-at": "Ngày tạo",
"title": "Tên truyện",
"description": "Tóm tắt",
"author": "Tác giả",
"latest-chapter": "Tập mới nhất",
"thumbnail": "Trang bìa",
"choose-genres": "Chọn thể loại",
"description_0": "Web đọc truyện tranh online lớn nhất được cập nhật liên tục mỗi ngày - Cùng tham gia đọc truyện và thảo luận với hơn 10 triệu thành viên 🎉 tại YouthBook ❤️💛💚"
}
23 changes: 22 additions & 1 deletion src/apis/comic.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ComicModel } from './../types/comic';
import { TopComicType } from './../types/request';
import apiClients from '@/configs/apiClients';
import { COMICS_PATH } from '@/constants/path';
import { ComicBaseData, ComicData } from '@/types/comic';
import { Comic, ComicBaseData, ComicData, Genres } from '@/types/comic';
import { paramOption } from '@/types/request';

const comicApis = {
Expand All @@ -27,6 +28,26 @@ const comicApis = {

return apiClients.get<ComicData>(url, { params: paramsRequest });
},

genresComics() {
const url = COMICS_PATH.genres;
return apiClients.get<Genres[]>(url);
},

getComicInfo(id: string | undefined) {
const url = COMICS_PATH.comics + `/${id ?? '-1'}`;
return apiClients.get<Comic>(url);
},

updateComic(id: string | undefined, comic: ComicModel) {
const url = COMICS_PATH.comics + `/${id ?? '-1'}`;
return apiClients.put<Comic>(url, { ...comic });
},

addComic(comic: ComicModel) {
const url = COMICS_PATH.add;
return apiClients.post<Comic>(url, { ...comic });
},
};

export default comicApis;
8 changes: 4 additions & 4 deletions src/components/Comics/ComicHorizontal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ const ComicHorizontal = ({ index, item, isSearchItem = true }: SearchItemProps)
{item.title}
</Link>
<Link
to={`${APP_PATH.comics_chapters}/${item._id}/${item.latest_chapter.slice(-1)[0].id}`}
title={item.latest_chapter.slice(-1)[0].name}
to={`${APP_PATH.comics_chapters}/${item._id}/${item.chapters[0].id}`}
title={item.chapters[0].name}
className="text-grey-800 text-sx mt-1 line-clamp-1 font-light capitalize italic">
{item.latest_chapter.slice(-1)[0].name}
{item.chapters[0].name}
</Link>
<p className={`mt-1 line-clamp-2 font-semibold text-blue-700`}>{item.authors}</p>
<p className={`mt-1 line-clamp-2 font-semibold text-blue-700`}>{item.author}</p>
<p className={`mt-1 line-clamp-2 italic text-black dark:text-white ${!isSearchItem && ' text-xs'}`}>
{Array.isArray(item.genres) && item.genres.map((genre) => genre.name).join(', ')}
</p>
Expand Down
14 changes: 7 additions & 7 deletions src/components/Comics/ComicVertical.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface ComicVerticalProps {
}

const ComicVertical = ({ data }: ComicVerticalProps) => {
const { _id: id, title, thumbnail, short_description } = data;
const { _id: id, title: title, thumbnail, description: short_description } = data;
const lang = useAppSelector((state) => selectLanguage(state.settings));
const translate = useTranslation(lang);

Expand Down Expand Up @@ -54,8 +54,8 @@ const ComicVertical = ({ data }: ComicVerticalProps) => {
{title}
</Link>
{data &&
data.latest_chapter &&
data.latest_chapter.slice(0, 3).map((chapter) => (
data.chapters &&
data.chapters.slice(0, 3).map((chapter) => (
<div
key={chapter.id}
className="mt-2">
Expand All @@ -66,7 +66,7 @@ const ComicVertical = ({ data }: ComicVerticalProps) => {
{chapter.name}
</Link>
<span className="float-right inline-block text-sm text-gray-400">
{new Date(chapter.updated_at).toLocaleDateString()}
{new Date(chapter.updatedAt).toLocaleDateString()}
</span>
</div>
))}
Expand All @@ -90,8 +90,8 @@ const ComicVertical = ({ data }: ComicVerticalProps) => {
{title}
</Link>
{data &&
data.latest_chapter &&
data.latest_chapter.map((chapter) => (
data.chapters &&
data.chapters.map((chapter) => (
<div
key={chapter.id}
className="mt-1">
Expand All @@ -102,7 +102,7 @@ const ComicVertical = ({ data }: ComicVerticalProps) => {
{chapter.name}
</Link>
<span className="float-right inline-block text-center text-sm text-gray-400">
{new Date(chapter.updated_at).toLocaleDateString()}
{new Date(chapter.updatedAt).toLocaleDateString()}
</span>
</div>
))}
Expand Down
93 changes: 93 additions & 0 deletions src/components/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useEffect, useState } from 'react';

interface DropDownPros {
data: { id: string; value: string; title: string }[] | undefined;
text: string;
value?: string[];
onChange?: (val: string[]) => void;
}

const DropDown = ({ text, data, value, onChange }: DropDownPros) => {
const [isHidden, setIsHidden] = useState<boolean>(true);
const [currentValue, setCurrentValue] = useState<string[]>();

useEffect(() => {
setCurrentValue(value);
}, [value]);

const handleCheck = (val: string) => {
const tempValue = currentValue || [];

const index = tempValue.indexOf(val);
if (index > -1) {
tempValue.splice(index, 1);
} else {
tempValue.push(val);
}

const uniqueValue = tempValue.filter((c, index) => {
return tempValue.indexOf(c) === index;
});

setCurrentValue(uniqueValue);
onChange && onChange(uniqueValue);
};

return (
<div className="relative h-full w-full">
<button
onClick={() => setIsHidden((prev) => !prev)}
id="dropdownBgHoverButton"
data-dropdown-toggle="dropdownBgHover"
className="inline-flex items-center rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
type="button">
{text}
<svg
className="ms-3 h-2.5 w-2.5"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 10 6">
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="m1 1 4 4 4-4"
/>
</svg>
</button>
<div
id="dropdownBgHover"
className={`${isHidden ? 'hidden' : ''} z-20 w-48 rounded-lg bg-white shadow dark:bg-gray-700`}>
<ul
className="space-y-1 p-3 text-sm text-gray-700 dark:text-gray-200"
aria-labelledby="dropdownBgHoverButton">
{data &&
data.map((e) => (
<li key={e.id}>
<div className="flex items-center rounded p-2 hover:bg-gray-100 dark:hover:bg-gray-600">
<input
key={e.id}
id={e.id}
onClick={() => handleCheck(e.value)}
type="checkbox"
defaultChecked={value && value.includes(e.value)}
value={e.value}
className="h-4 w-4 rounded border-gray-300 bg-gray-100 text-blue-600 focus:ring-2 focus:ring-blue-500 dark:border-gray-500 dark:bg-gray-600 dark:ring-offset-gray-700 dark:focus:ring-blue-600 dark:focus:ring-offset-gray-700"
/>
<label
htmlFor={e.id}
className="ms-2 w-full rounded text-sm font-medium text-gray-900 dark:text-gray-300">
{e.title}
</label>
</div>
</li>
))}
</ul>
</div>
</div>
);
};

export default DropDown;
2 changes: 1 addition & 1 deletion src/components/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const Popup = ({ closeHandle, title, content, submit = true, cancel = true, subm
<span className="sr-only">Close modal</span>
</button>
</div>
<div className="space-y-4 p-4 md:p-5">{content}</div>
<div className="max-h-[500px] space-y-4 overflow-y-auto p-4 md:p-5">{content}</div>
<div className="flex items-center justify-end gap-4 rounded-b border-t border-gray-200 p-4 dark:border-gray-600 md:p-5">
{cancel && (
<button
Expand Down
2 changes: 1 addition & 1 deletion src/components/Preview/TopPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const TopPreview = ({ data, top = 7 }: TopPreviewProps) => {
{item.title}
</Link>
<p className="ml-[1px] line-clamp-1 text-sm leading-5 text-gray-400">
{item.total_views} {translate('views')}
{item.totalViews} {translate('views')}
</p>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/constants/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export const COMICS_PATH = {
recent: '/comics/recent',
recommend: '/comics/recommend',
search: '/comics/search',
genres: '/comics/genres',
add: '/comics/add',
} as const;

export const AUTH_PATH = {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Management/BillingManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const BillingManagement: React.FC = () => {
return <>Billing Management</>;
return <div className="relative h-full w-full overflow-x-auto border-2 p-8 sm:rounded-lg">Billing Management</div>;
};

export default BillingManagement;
Loading

0 comments on commit fec5ef3

Please sign in to comment.