This commit is contained in:
Anang Yusman 2025-10-06 23:22:33 +08:00
parent 5bef0f2061
commit d931ec600d
5 changed files with 143 additions and 20 deletions

View File

@ -6,6 +6,7 @@ import { getArticleById, getListArticle } from "@/service/article";
import { close, loading } from "@/config/swal"; import { close, loading } from "@/config/swal";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import Author from "../landing-page/author"; import Author from "../landing-page/author";
import { Link2, MailIcon } from "lucide-react";
type TabKey = "trending" | "comments" | "latest"; type TabKey = "trending" | "comments" | "latest";
@ -366,7 +367,48 @@ export default function DetailContent() {
}} }}
/> />
</div> </div>
<Author /> {/* <Author /> */}
<div className="w-full bg-white py-6">
<p className="mx-10 text-2xl mb-4 ">AUTHOR</p>
<div className=" border border-black p-6 flex items-center gap-6 max-w-[1200px] mx-auto">
{/* Foto Profil */}
<div className="w-20 h-20 relative ">
<Image
src="/profile.jpg"
alt="Author"
fill
className="rounded-full object-cover"
/>
</div>
{/* Info Author */}
<div className="flex-1">
<h3 className="text-lg font-semibold text-gray-800">
{articleDetail?.createdByName}
</h3>
<div className="mt-2 flex items-center gap-4 flex-wrap">
{/* Button lihat semua post */}
<button className="text-sm font-medium text-white hover:underline bg-[#655997] py-1 px-5 rounded-xl">
Lihat Semua Pos
</button>
<div className="bg-[#655997] rounded-full p-1">
<MailIcon
size={18}
className="text-white hover:text-black cursor-pointer "
></MailIcon>
</div>
<div className="bg-[#655997] rounded-full p-1">
<Link2
size={18}
className="text-white hover:text-black cursor-pointer "
></Link2>
</div>
</div>
</div>
</div>
</div>
<div className="flex flex-row gap-2 items-center"> <div className="flex flex-row gap-2 items-center">
<span className="font-semibold text-sm text-gray-700"> <span className="font-semibold text-sm text-gray-700">
Tags: Tags:

View File

@ -46,6 +46,7 @@ import {
TableCell, TableCell,
} from "@/components/ui/table"; } from "@/components/ui/table";
import CustomPagination from "../layout/custom-pagination"; import CustomPagination from "../layout/custom-pagination";
import DatePicker from "react-datepicker";
const columns = [ const columns = [
{ name: "No", uid: "no" }, { name: "No", uid: "no" },
@ -60,6 +61,7 @@ const columns = [
const columnsOtherRole = [ const columnsOtherRole = [
{ name: "No", uid: "no" }, { name: "No", uid: "no" },
{ name: "Judul", uid: "title" }, { name: "Judul", uid: "title" },
{ name: "Source", uid: "source" },
{ name: "Kategori", uid: "category" }, { name: "Kategori", uid: "category" },
{ name: "Tanggal Unggah", uid: "createdAt" }, { name: "Tanggal Unggah", uid: "createdAt" },
{ name: "Kreator", uid: "createdByName" }, { name: "Kreator", uid: "createdByName" },
@ -84,7 +86,9 @@ export default function ArticleTable() {
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [categories, setCategories] = useState<any>([]); const [categories, setCategories] = useState<any>([]);
const [selectedCategories, setSelectedCategories] = useState<any>(""); const [selectedCategories, setSelectedCategories] = useState<any>("");
const [startDateValue, setStartDateValue] = useState({ const [selectedSource, setSelectedSource] = useState<any>("");
const [selectedStatus, setSelectedStatus] = useState<string>("");
const [dateRange, setDateRange] = useState<any>({
startDate: null, startDate: null,
endDate: null, endDate: null,
}); });
@ -98,24 +102,49 @@ export default function ArticleTable() {
const res = await getArticleByCategory(); const res = await getArticleByCategory();
const data = res?.data?.data; const data = res?.data?.data;
setCategories(data); setCategories(data);
console.log("category", data);
} }
useEffect(() => {
initState();
}, [
page,
showData,
search,
selectedCategories,
selectedSource,
dateRange,
selectedStatus,
]);
async function initState() { async function initState() {
loading(); loading();
const req = { const req = {
limit: showData, limit: showData,
page: page, page: page,
search: search, search: search,
categorySlug: Array.from(selectedCategories).join(","), category: selectedCategories || "",
source: selectedSource || "",
isPublish:
selectedStatus !== "" ? selectedStatus === "publish" : undefined,
startDate: dateRange.startDate
? new Date(dateRange.startDate).toISOString()
: "",
endDate: dateRange.endDate
? new Date(dateRange.endDate).toISOString()
: "",
sort: "desc", sort: "desc",
sortBy: "created_at", sortBy: "created_at",
}; };
const res = await getArticlePagination(req); const res = await getArticlePagination(req);
await getTableNumber(parseInt(showData), res.data?.data);
let data = res.data?.data || [];
await getTableNumber(parseInt(showData), data);
setTotalPage(res?.data?.meta?.totalPage); setTotalPage(res?.data?.meta?.totalPage);
close(); close();
} }
// panggil ulang setiap state berubah // panggil ulang setiap state berubah
useEffect(() => { useEffect(() => {
initState(); initState();
@ -346,24 +375,63 @@ export default function ArticleTable() {
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{categories {categories
?.filter((category: any) => category.slug != null) ?.filter((category: any) => category.title != null)
.map((category: any) => ( .map((category: any) => (
<SelectItem key={category.slug} value={category.slug}> <SelectItem key={category.id} value={category.title}>
{category.title} {category.title}
</SelectItem> </SelectItem>
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
{/* <div className="flex flex-col gap-1 w-full lg:w-[240px]"> <div className="flex flex-col gap-1 w-full lg:w-[150px]">
<p className="font-semibold text-sm">Source</p>
<Select
value={selectedSource}
onValueChange={(value) => setSelectedSource(value)}
>
<SelectTrigger className="w-full text-sm border">
<SelectValue placeholder="Pilih Source" />
</SelectTrigger>
<SelectContent>
<SelectItem value="INTERNAL">INTERNAL</SelectItem>
<SelectItem value="EXTERNAL">EXTERNAL</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex flex-col gap-1 w-full lg:w-[150px]">
<p className="font-semibold text-sm">Status</p>
<Select
value={selectedStatus}
onValueChange={(value) => setSelectedStatus(value)}
>
<SelectTrigger className="w-full text-sm border">
<SelectValue placeholder="Pilih Status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="publish">PUBLISH</SelectItem>
<SelectItem value="draft">DRAFT</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex flex-col gap-1 w-full lg:w-[240px]">
<p className="font-semibold text-sm">Tanggal</p> <p className="font-semibold text-sm">Tanggal</p>
<Datepicker <DatePicker
value={startDateValue} selectsRange
displayFormat="DD/MM/YYYY" startDate={dateRange.startDate}
onChange={(e: any) => setStartDateValue(e)} endDate={dateRange.endDate}
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" onChange={(update: [Date | null, Date | null]) => {
setDateRange({
startDate: update[0],
endDate: update[1],
});
}}
isClearable
dateFormat="dd/MM/yyyy"
className="z-50 w-full text-sm bg-transparent border border-gray-200 px-2 py-[6px] rounded-xl h-[40px] text-gray-600 dark:text-gray-300"
placeholderText="Pilih rentang tanggal"
/> />
</div> */} </div>
</div> </div>
<div className="w-full overflow-x-hidden"> <div className="w-full overflow-x-hidden">
<div className="w-full mx-auto overflow-x-hidden"> <div className="w-full mx-auto overflow-x-hidden">

BIN
public/profile.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,6 +1,11 @@
import { PaginationRequest } from "@/types/globals"; import { PaginationRequest } from "@/types/globals";
import { httpGet } from "./http-config/http-base-services"; import { httpGet } from "./http-config/http-base-services";
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services"; import {
httpDeleteInterceptor,
httpGetInterceptor,
httpPostInterceptor,
httpPutInterceptor,
} from "./http-config/http-interceptor-services";
export async function getListArticle(props: PaginationRequest) { export async function getListArticle(props: PaginationRequest) {
const { const {
@ -40,13 +45,20 @@ export async function getArticlePagination(props: PaginationRequest) {
sort, sort,
categorySlug, categorySlug,
isBanner, isBanner,
isPublish,
source,
} = props; } = props;
return await httpGetInterceptor( return await httpGetInterceptor(
`/articles?limit=${limit}&page=${page}&title=${search}&startDate=${startDate || ""}&endDate=${ `/articles?limit=${limit}&page=${page}&title=${search}&startDate=${
endDate || "" startDate || ""
}&categoryId=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${ }&endDate=${endDate || ""}&categoryId=${category || ""}&source=${
sort || "asc" source || ""
}&category=${categorySlug || ""}&isBanner=${isBanner || ""}` }&isPublish=${isPublish !== undefined ? isPublish : ""}&sortBy=${
sortBy || "created_at"
}&sort=${sort || "asc"}&category=${categorySlug || ""}&isBanner=${
isBanner || ""
}`
); );
} }

View File

@ -310,6 +310,7 @@ export type PaginationRequest = {
category?: string; category?: string;
sortBy?: string; sortBy?: string;
sort?: string; sort?: string;
source?: string;
categorySlug?: string; categorySlug?: string;
isBanner?: boolean; isBanner?: boolean;
}; };