merge restructure
This commit is contained in:
commit
79724453f1
|
|
@ -159,6 +159,10 @@ export default function DetailNews(props: { data: any; listArticle: any }) {
|
|||
<div className="flex justify-center my-2 lg:my-5">
|
||||
{data?.files?.length > 0 && (
|
||||
<Image
|
||||
classNames={{
|
||||
wrapper: "!w-full !max-w-full",
|
||||
img: "!w-full",
|
||||
}}
|
||||
alt="Main Image"
|
||||
src={data?.files[imageNow]?.file_url}
|
||||
className="object-cover w-[100%] rounded-md"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
DotsYIcon,
|
||||
EyeIconMdi,
|
||||
SearchIcon,
|
||||
TimesIcon,
|
||||
} from "@/components/icons";
|
||||
import { close, error, loading, success, successToast } from "@/config/swal";
|
||||
import {
|
||||
|
|
@ -16,9 +17,16 @@ import {
|
|||
updateIsBannerArticle,
|
||||
} from "@/services/article";
|
||||
import { Article } from "@/types/globals";
|
||||
import { convertDateFormat } from "@/utils/global";
|
||||
import {
|
||||
convertDateFormat,
|
||||
convertDateFormatNoTime,
|
||||
convertDateFormatNoTimeV2,
|
||||
} from "@/utils/global";
|
||||
import { Button } from "@heroui/button";
|
||||
import {
|
||||
Autocomplete,
|
||||
AutocompleteItem,
|
||||
Calendar,
|
||||
Chip,
|
||||
ChipProps,
|
||||
Dropdown,
|
||||
|
|
@ -27,6 +35,9 @@ import {
|
|||
DropdownTrigger,
|
||||
Input,
|
||||
Pagination,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
Select,
|
||||
SelectItem,
|
||||
Spinner,
|
||||
|
|
@ -43,6 +54,10 @@ import Datepicker from "react-tailwindcss-datepicker";
|
|||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import Cookies from "js-cookie";
|
||||
import { parseDate } from "@internationalized/date";
|
||||
import { listMasterUsers } from "@/services/master-user";
|
||||
import ReactSelect from "react-select";
|
||||
import makeAnimated from "react-select/animated";
|
||||
|
||||
const columns = [
|
||||
{ name: "No", uid: "no" },
|
||||
|
|
@ -79,6 +94,7 @@ export default function ArticleTable() {
|
|||
const MySwal = withReactContent(Swal);
|
||||
const username = Cookies.get("username");
|
||||
const userId = Cookies.get("uie");
|
||||
const animatedComponents = makeAnimated();
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [totalPage, setTotalPage] = useState(1);
|
||||
|
|
@ -86,36 +102,110 @@ export default function ArticleTable() {
|
|||
const [showData, setShowData] = useState("10");
|
||||
const [search, setSearch] = useState("");
|
||||
const [categories, setCategories] = useState<any>([]);
|
||||
const [users, setUsers] = useState<any>([]);
|
||||
const [selectedCategories, setSelectedCategories] = useState<any>([]);
|
||||
const [selectedUsers, setSelectedUsers] = useState<any>([]);
|
||||
const [startDateValue, setStartDateValue] = useState({
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
});
|
||||
|
||||
const [articleDate, setArticleDate] = useState<{
|
||||
startDate: any;
|
||||
endDate: any;
|
||||
}>({
|
||||
startDate: parseDate(
|
||||
convertDateFormatNoTimeV2(
|
||||
new Date(new Date().setDate(new Date().getDate() - 7))
|
||||
)
|
||||
),
|
||||
endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
initState();
|
||||
}, [page, showData, startDateValue, selectedCategories]);
|
||||
}, [
|
||||
page,
|
||||
showData,
|
||||
startDateValue,
|
||||
selectedCategories,
|
||||
articleDate,
|
||||
selectedUsers,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
getCategories();
|
||||
getUsers();
|
||||
}, []);
|
||||
|
||||
const setupList = (data: any, type: string) => {
|
||||
const temp = [];
|
||||
for (const element of data) {
|
||||
temp.push({
|
||||
id: element.id,
|
||||
label: element.title || element.fullname,
|
||||
value: element.id,
|
||||
});
|
||||
}
|
||||
if (type === "users") {
|
||||
setUsers(temp);
|
||||
}
|
||||
|
||||
if (type === "category") {
|
||||
setCategories(temp);
|
||||
}
|
||||
};
|
||||
|
||||
async function getUsers() {
|
||||
const res = await listMasterUsers({ page: page, limit: -1 });
|
||||
setupList(res?.data?.data, "users");
|
||||
}
|
||||
|
||||
async function getCategories() {
|
||||
const res = await getArticleByCategory();
|
||||
const data = res?.data?.data;
|
||||
setCategories(data);
|
||||
setupList(res?.data?.data, "category");
|
||||
}
|
||||
|
||||
const onSelectionChange = (id: Key | null) => {
|
||||
setSelectedCategories(String(id));
|
||||
};
|
||||
|
||||
const getDate = (data: any) => {
|
||||
if (data === null) {
|
||||
return "";
|
||||
} else {
|
||||
return `${data.year}-${data.month < 10 ? `0${data.month}` : data.month}-${
|
||||
data.day < 10 ? `0${data.day}` : data.day
|
||||
}`;
|
||||
}
|
||||
};
|
||||
|
||||
const getIds = (data: { id: number; label: string; value: number }[]) => {
|
||||
let temp = "";
|
||||
if (data) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (i == 0) {
|
||||
temp = String(data[i].id);
|
||||
} else {
|
||||
temp = temp + `,${data[i].id}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
};
|
||||
|
||||
async function initState() {
|
||||
loading();
|
||||
console.log("test", getIds(selectedCategories));
|
||||
const req = {
|
||||
limit: showData,
|
||||
page: page,
|
||||
search: search,
|
||||
// startDate:
|
||||
// startDateValue.startDate === null ? "" : startDateValue.startDate,
|
||||
// endDate: startDateValue.endDate === null ? "" : startDateValue.endDate,
|
||||
categorySlug: Array.from(selectedCategories).join(","),
|
||||
startDate: getDate(articleDate.startDate),
|
||||
endDate: getDate(articleDate.endDate),
|
||||
categoryIds: getIds(selectedCategories),
|
||||
createdByIds: getIds(selectedUsers),
|
||||
sort: "desc",
|
||||
sortBy: "created_at",
|
||||
};
|
||||
|
|
@ -248,13 +338,13 @@ export default function ArticleTable() {
|
|||
<DropdownItem
|
||||
key="edit"
|
||||
className={
|
||||
username === "admin-mabes" ||
|
||||
username?.includes("mabes") ||
|
||||
Number(userId) === article.createdById
|
||||
? ""
|
||||
: "hidden"
|
||||
}
|
||||
>
|
||||
{(username === "admin-mabes" ||
|
||||
{(username?.includes("mabes") ||
|
||||
Number(userId) === article.createdById) && (
|
||||
<Link href={`/admin/article/edit/${article.id}`}>
|
||||
<CreateIconIon className="inline mr-2 mb-1" />
|
||||
|
|
@ -267,9 +357,9 @@ export default function ArticleTable() {
|
|||
onPress={() =>
|
||||
handleBanner(article?.id, !article?.isBanner)
|
||||
}
|
||||
className={username === "admin-mabes" ? "" : "hidden"}
|
||||
className={username?.includes("mabes") ? "" : "hidden"}
|
||||
>
|
||||
{username === "admin-mabes" && (
|
||||
{username?.includes("mabes") && (
|
||||
<>
|
||||
<BannerIcon size={24} className="inline mr-2 mb-1" />
|
||||
{article?.isBanner
|
||||
|
|
@ -282,13 +372,13 @@ export default function ArticleTable() {
|
|||
key="delete"
|
||||
onPress={() => handleDelete(article.id)}
|
||||
className={
|
||||
username === "admin-mabes" ||
|
||||
username?.includes("mabes") ||
|
||||
Number(userId) === article.createdById
|
||||
? ""
|
||||
: "hidden"
|
||||
}
|
||||
>
|
||||
{(username === "admin-mabes" ||
|
||||
{(username?.includes("mabes") ||
|
||||
Number(userId) === article.createdById) && (
|
||||
<>
|
||||
{" "}
|
||||
|
|
@ -330,6 +420,15 @@ export default function ArticleTable() {
|
|||
initState();
|
||||
}
|
||||
|
||||
const [hasMounted, setHasMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setHasMounted(true);
|
||||
}, []);
|
||||
|
||||
// Render
|
||||
if (!hasMounted) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="py-3">
|
||||
|
|
@ -375,44 +474,155 @@ export default function ArticleTable() {
|
|||
</div>
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[230px]">
|
||||
<p className="font-semibold text-sm">Kategori</p>
|
||||
<Select
|
||||
label=""
|
||||
variant="bordered"
|
||||
labelPlacement="outside"
|
||||
placeholder="Kategori"
|
||||
selectionMode="single"
|
||||
selectedKeys={selectedCategories}
|
||||
className="w-full"
|
||||
items={categories}
|
||||
classNames={{ trigger: "border-1" }}
|
||||
onSelectionChange={setSelectedCategories}
|
||||
renderValue={(items) => {
|
||||
return items.map((item) => (
|
||||
<span
|
||||
key={item.props?.value}
|
||||
className="text-black dark:text-white text-xs"
|
||||
>
|
||||
{item.textValue}
|
||||
</span>
|
||||
));
|
||||
<ReactSelect
|
||||
className="basic-single text-black z-50"
|
||||
classNames={{
|
||||
control: (state: any) =>
|
||||
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
|
||||
}}
|
||||
>
|
||||
{categories?.map((category: any) => (
|
||||
<SelectItem key={category?.slug}>
|
||||
{category?.title}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
{/* <div className="flex flex-col gap-1 w-full lg:w-[240px]">
|
||||
<p className="font-semibold text-sm">Tanggal</p>
|
||||
<Datepicker
|
||||
value={startDateValue}
|
||||
displayFormat="DD/MM/YYYY"
|
||||
onChange={(e: any) => setStartDateValue(e)}
|
||||
inputClassName="z-50 w-full text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-xl h-[40px] text-gray-600 dark:text-gray-300"
|
||||
classNamePrefix="select"
|
||||
onChange={setSelectedCategories}
|
||||
closeMenuOnSelect={false}
|
||||
components={animatedComponents}
|
||||
isClearable={true}
|
||||
isSearchable={true}
|
||||
isMulti={true}
|
||||
placeholder="Kategori..."
|
||||
name="sub-module"
|
||||
options={categories}
|
||||
// styles={{
|
||||
// control: (base) => ({
|
||||
// ...base,
|
||||
// width: "100%",
|
||||
// overflowX: "auto",
|
||||
// }),
|
||||
// valueContainer: (base) => ({
|
||||
// ...base,
|
||||
// display: "flex",
|
||||
// flexWrap: "nowrap",
|
||||
// overflowX: "auto",
|
||||
// whiteSpace: "nowrap",
|
||||
// gap: "4px",
|
||||
// }),
|
||||
// multiValue: (base) => ({
|
||||
// ...base,
|
||||
// whiteSpace: "nowrap",
|
||||
// flexShrink: 0,
|
||||
// }),
|
||||
// multiValueLabel: (base) => ({
|
||||
// ...base,
|
||||
// whiteSpace: "nowrap",
|
||||
// }),
|
||||
// }}
|
||||
/>
|
||||
</div> */}
|
||||
</div>
|
||||
{username?.includes("mabes") && (
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[230px]">
|
||||
<p className="font-semibold text-sm">Author</p>
|
||||
|
||||
<ReactSelect
|
||||
className="basic-single text-black z-50"
|
||||
classNames={{
|
||||
control: (state: any) =>
|
||||
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
|
||||
}}
|
||||
classNamePrefix="select"
|
||||
onChange={setSelectedUsers}
|
||||
closeMenuOnSelect={false}
|
||||
components={animatedComponents}
|
||||
isClearable={true}
|
||||
isSearchable={true}
|
||||
isMulti={true}
|
||||
placeholder="Kategori..."
|
||||
name="sub-module"
|
||||
options={users}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[140px]">
|
||||
<p className="font-semibold text-sm">Start Date</p>
|
||||
|
||||
<Popover
|
||||
placement="bottom"
|
||||
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
<div className="flex flex-row gap-1 items-center cursor-pointer border-1 px-2 py-2 rounded-xl">
|
||||
<a className=" w-[120px]">
|
||||
{articleDate.startDate
|
||||
? convertDateFormatNoTime(articleDate.startDate)
|
||||
: "-"}
|
||||
</a>
|
||||
{articleDate.startDate && (
|
||||
<a
|
||||
onClick={() =>
|
||||
setArticleDate({
|
||||
startDate: null,
|
||||
endDate: articleDate.endDate,
|
||||
})
|
||||
}
|
||||
>
|
||||
<TimesIcon size={16} />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="bg-transparent">
|
||||
<Calendar
|
||||
value={articleDate.startDate}
|
||||
onChange={(e) =>
|
||||
setArticleDate({
|
||||
startDate: e,
|
||||
endDate: articleDate.endDate,
|
||||
})
|
||||
}
|
||||
maxValue={articleDate.endDate}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[120px]">
|
||||
<p className="font-semibold text-sm">End Date</p>
|
||||
|
||||
<Popover
|
||||
placement="bottom"
|
||||
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
<div className="flex flex-row gap-1 items-center cursor-pointer border-1 px-2 py-2 rounded-xl">
|
||||
<a className=" w-[120px]">
|
||||
{articleDate.endDate
|
||||
? convertDateFormatNoTime(articleDate.endDate)
|
||||
: "-"}
|
||||
</a>
|
||||
{articleDate.endDate && (
|
||||
<a
|
||||
onClick={() =>
|
||||
setArticleDate({
|
||||
endDate: null,
|
||||
startDate: articleDate.startDate,
|
||||
})
|
||||
}
|
||||
>
|
||||
<TimesIcon size={16} />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="bg-transparent">
|
||||
<Calendar
|
||||
value={articleDate.endDate}
|
||||
onChange={(e) =>
|
||||
setArticleDate({
|
||||
startDate: articleDate.startDate,
|
||||
endDate: e,
|
||||
})
|
||||
}
|
||||
minValue={articleDate.startDate}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
<Table
|
||||
aria-label="micro issue table"
|
||||
|
|
@ -425,7 +635,7 @@ export default function ArticleTable() {
|
|||
}}
|
||||
>
|
||||
<TableHeader
|
||||
columns={username === "admin-mabes" ? columns : columnsOtherRole}
|
||||
columns={username?.includes("mabes") ? columns : columnsOtherRole}
|
||||
>
|
||||
{(column) => (
|
||||
<TableColumn key={column.uid}>{column.name}</TableColumn>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ export async function getListArticle(props: PaginationRequest) {
|
|||
sort,
|
||||
categorySlug,
|
||||
isBanner,
|
||||
categoryIds,
|
||||
createdByIds,
|
||||
} = props;
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
|
|
@ -33,8 +35,10 @@ export async function getListArticle(props: PaginationRequest) {
|
|||
}&title=${search}&startDate=${startDate || ""}&endDate=${
|
||||
endDate || ""
|
||||
}&categoryId=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${
|
||||
sort || "desc"
|
||||
}&category=${categorySlug || ""}&isBanner=${isBanner || ""}`,
|
||||
sort || "asc"
|
||||
}&category=${categorySlug || ""}&isBanner=${isBanner || ""}&categoryIds=${
|
||||
categoryIds || ""
|
||||
}&createdByIds=${createdByIds || ""}`,
|
||||
headers
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,4 +67,6 @@ export type PaginationRequest = {
|
|||
sort?: string;
|
||||
categorySlug?: string;
|
||||
isBanner?: boolean;
|
||||
categoryIds?: string;
|
||||
createdByIds?: string;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue