pull main

This commit is contained in:
Sabda Yagra 2025-07-28 08:32:29 +07:00
commit 2f7461be46
50 changed files with 1214 additions and 19647 deletions

View File

@ -7,6 +7,7 @@ build-dev:
when: on_success when: on_success
only: only:
- main - main
- dev-landing-v2
image: docker:stable image: docker:stable
services: services:
- name: docker:dind - name: docker:dind
@ -22,6 +23,7 @@ auto-deploy:
when: on_success when: on_success
only: only:
- main - main
- dev-landing-v2
image: curlimages/curl:latest image: curlimages/curl:latest
services: services:
- docker:dind - docker:dind

View File

@ -25,7 +25,7 @@ RUN pnpm install
COPY . . COPY . .
# Build aplikasi # Build aplikasi
RUN NODE_OPTIONS="--max-old-space-size=4096" pnpm next build RUN NODE_OPTIONS="--max-old-space-size=4096" pnpm run build
# Expose port untuk server # Expose port untuk server
EXPOSE 3000 EXPOSE 3000

View File

@ -76,9 +76,6 @@ export default function EditUserForm() {
}, },
}); });
const passwordVal = form.watch("password");
const confPasswordVal = form.watch("confirmPassword");
useEffect(() => { useEffect(() => {
initData(); initData();
}, []); }, []);

View File

@ -353,8 +353,8 @@ export default function EditUserForm() {
<PasswordChecklist <PasswordChecklist
rules={["minLength", "specialChar", "number", "capital", "match"]} rules={["minLength", "specialChar", "number", "capital", "match"]}
minLength={8} minLength={8}
value={passwordVal} value={passwordVal || ""}
valueAgain={confPasswordVal} valueAgain={confPasswordVal || ""}
onChange={(isValid) => { onChange={(isValid) => {
form.setValue("isValidPassword", isValid); form.setValue("isValidPassword", isValid);
}} }}

View File

@ -751,8 +751,8 @@ export default function CreateUserForm() {
<PasswordChecklist <PasswordChecklist
rules={["minLength", "specialChar", "number", "capital", "match"]} rules={["minLength", "specialChar", "number", "capital", "match"]}
minLength={8} minLength={8}
value={passwordVal} value={passwordVal || ""}
valueAgain={confPasswordVal} valueAgain={confPasswordVal || ""}
onChange={(isValid) => { onChange={(isValid) => {
form.setValue("isValidPassword", isValid); form.setValue("isValidPassword", isValid);
}} }}

View File

@ -191,8 +191,6 @@ export default function DetailUserForm() {
}, },
}); });
const passwordVal = form.watch("password");
const confPasswordVal = form.watch("confirmPassword");
const selectedRole = form.watch("role"); const selectedRole = form.watch("role");
useEffect(() => { useEffect(() => {

View File

@ -756,8 +756,8 @@ export default function EditUserForm() {
<PasswordChecklist <PasswordChecklist
rules={["minLength", "specialChar", "number", "capital", "match"]} rules={["minLength", "specialChar", "number", "capital", "match"]}
minLength={8} minLength={8}
value={passwordVal} value={passwordVal || ""}
valueAgain={confPasswordVal} valueAgain={confPasswordVal || ""}
onChange={(isValid) => { onChange={(isValid) => {
form.setValue("isValidPassword", isValid); form.setValue("isValidPassword", isValid);
}} }}

View File

@ -125,16 +125,16 @@ export default function CreateCategoryModal() {
}); });
const contentType = form.watch("contentType"); const contentType = form.watch("contentType");
const isAllContentChecked = listContent.every((item) => const isAllContentChecked = contentType && listContent.every((item) =>
contentType?.includes(item.id) contentType.includes(item.id)
); );
const users = form.watch("selectedUser"); const users = form.watch("selectedUser");
const isAllUserChecked = userList.every((item) => users?.includes(item.id)); const isAllUserChecked = users && userList.every((item) => users.includes(item.id));
const target = form.watch("publishTo"); const target = form.watch("publishTo");
const isAllTargetChecked = publishToList.every((item) => const isAllTargetChecked = target && publishToList.every((item) =>
target?.includes(item.id) target.includes(item.id)
); );
const { getRootProps, getInputProps } = useDropzone({ const { getRootProps, getInputProps } = useDropzone({

View File

@ -146,12 +146,12 @@ export default function EditCategoryModal(props: {
form.setValue("id", String(data?.id)); form.setValue("id", String(data?.id));
form.setValue("title", String(data?.name)); form.setValue("title", String(data?.name));
form.setValue("description", String(data?.description)); form.setValue("description", String(data?.description));
form.setValue("contentType", data?.mediaTypes?.split(",")); form.setValue("contentType", data?.mediaTypes?.split(",") || []);
form.setValue( form.setValue(
"selectedUser", "selectedUser",
removeAndReturn(data?.publishedFor, [2, 3, 4]) removeAndReturn(data?.publishedFor, [2, 3, 4])
); );
form.setValue("publishTo", data?.publishedLocation?.split(",")); form.setValue("publishTo", data?.publishedLocation?.split(",") || []);
form.setValue("file", thumbnailLink); form.setValue("file", thumbnailLink);
setUnitData(filterString(data?.publishedLocationLevel, "under")); setUnitData(filterString(data?.publishedLocationLevel, "under"));
@ -183,16 +183,16 @@ export default function EditCategoryModal(props: {
} }
const contentType = form.watch("contentType"); const contentType = form.watch("contentType");
const isAllContentChecked = listContent.every((item) => const isAllContentChecked = contentType && listContent.every((item) =>
contentType?.includes(item.id) contentType.includes(item.id)
); );
const users = form.watch("selectedUser"); const users = form.watch("selectedUser");
const isAllUserChecked = userList.every((item) => users?.includes(item.id)); const isAllUserChecked = users && userList.every((item) => users.includes(item.id));
const target = form.watch("publishTo"); const target = form.watch("publishTo");
const isAllTargetChecked = publishToList.every((item) => const isAllTargetChecked = target && publishToList.every((item) =>
target?.includes(item.id) target.includes(item.id)
); );
useEffect(() => { useEffect(() => {

View File

@ -68,11 +68,11 @@ export function UnitMapping(props: {
const unitType = form.watch("items"); const unitType = form.watch("items");
const isAllUnitChecked = unitList.every((item) => const isAllUnitChecked = unitType && unitList.every((item) =>
unitType?.includes(String(item.id)) unitType.includes(String(item.id))
); );
const isAllSatkerChecked = satkerList.every((item) => const isAllSatkerChecked = unitType && satkerList.every((item) =>
unitType?.includes(String(item.id)) unitType.includes(String(item.id))
); );
const setupUnit = (data: UnitType[]) => { const setupUnit = (data: UnitType[]) => {

View File

@ -91,8 +91,8 @@ export default function CreateFAQModal() {
}); });
const target = form.watch("publishTo"); const target = form.watch("publishTo");
const isAllTargetChecked = publishToList.every((item) => const isAllTargetChecked = target && publishToList.every((item) =>
target?.includes(item.id) target.includes(item.id)
); );
const onSubmit = async (data: z.infer<typeof FormSchema>) => { const onSubmit = async (data: z.infer<typeof FormSchema>) => {

View File

@ -74,11 +74,11 @@ export function UnitMapping(props: {
const unitType = form.watch("items"); const unitType = form.watch("items");
const isAllUnitChecked = unitList.every((item) => const isAllUnitChecked = unitType && unitList.every((item) =>
unitType?.includes(String(item.id)) unitType.includes(String(item.id))
); );
const isAllSatkerChecked = satkerList.every((item) => const isAllSatkerChecked = unitType && satkerList.every((item) =>
unitType?.includes(String(item.id)) unitType.includes(String(item.id))
); );
const isAllPolresChecked = polresList.every((item) => const isAllPolresChecked = polresList.every((item) =>
unitType?.includes(String(item.id)) unitType?.includes(String(item.id))

View File

@ -132,29 +132,36 @@ const useTableColumns = () => {
accessorKey: "statusName", accessorKey: "statusName",
header: "Status", header: "Status",
cell: ({ row }) => { cell: ({ row }) => {
const statusColors: Record<string, string> = { const statusId = Number(row.original?.statusId);
diterima: "bg-green-100 text-green-600", const reviewedAtLevel = row.original?.reviewedAtLevel || "";
"menunggu review": "bg-orange-100 text-orange-600", const creatorGroupLevelId = Number(row.original?.creatorGroupLevelId);
const needApprovalFromLevel = Number(
row.original?.needApprovalFromLevel
);
const userHasReviewed = reviewedAtLevel.includes(`:${userLevelId}:`);
const isCreator = creatorGroupLevelId === Number(userLevelId);
const isWaitingForReview =
statusId === 2 && !userHasReviewed && !isCreator;
const isApprovalNeeded =
statusId === 1 && needApprovalFromLevel === Number(userLevelId);
const label =
isWaitingForReview || isApprovalNeeded
? "Menunggu Review"
: statusId === 2
? "Diterima"
: row.original?.statusName;
const colors: Record<string, string> = {
"Menunggu Review": "bg-orange-100 text-orange-600",
Diterima: "bg-green-100 text-green-600",
default: "bg-red-200 text-red-600",
}; };
const colors = [ const statusStyles = colors[label] || colors.default;
"bg-orange-100 text-orange-600",
"bg-orange-100 text-orange-600",
"bg-green-100 text-green-600",
"bg-blue-100 text-blue-600",
"bg-red-200 text-red-600",
];
const status =
Number(row.original?.statusId) == 2 &&
row.original?.reviewedAtLevel !== null &&
!row.original?.reviewedAtLevel?.includes(`:${userLevelId}:`) &&
Number(row.original?.creatorGroupLevelId) != Number(userLevelId)
? "1"
: row.original?.statusId;
const statusStyles =
colors[Number(status)] || "bg-red-200 text-red-600";
// const statusStyles = statusColors[status] || "bg-red-200 text-red-600";
return ( return (
<Badge <Badge
@ -163,18 +170,7 @@ const useTableColumns = () => {
statusStyles statusStyles
)} )}
> >
{(Number(row.original?.statusId) == 2 && {label}
!row.original?.reviewedAtLevel !== null &&
!row.original?.reviewedAtLevel?.includes(
`:${Number(userLevelId)}:`
) &&
Number(row.original?.creatorGroupLevelId) !=
Number(userLevelId)) ||
(Number(row.original?.statusId) == 1 &&
Number(row.original?.needApprovalFromLevel) ==
Number(userLevelId))
? "Menunggu Review"
: row.original?.statusName}{" "}
</Badge> </Badge>
); );
}, },

View File

@ -281,11 +281,11 @@ export default function DetailDaily() {
const output = form.watch("output"); const output = form.watch("output");
const isAllChecked = items.every((item) => output?.includes(item.id)); const isAllChecked = output && items.every((item) => output.includes(item.id));
const unit = form.watch("unit"); const unit = form.watch("unit");
const isAllUnitChecked = units.every((item) => unit?.includes(item.id)); const isAllUnitChecked = unit && units.every((item) => unit.includes(item.id));
const handleAllCheckedChange = (checked: boolean | string) => { const handleAllCheckedChange = (checked: boolean | string) => {
if (checked) { if (checked) {
@ -301,7 +301,7 @@ export default function DetailDaily() {
const handleItemCheckedChange = (id: string, checked: boolean | string) => { const handleItemCheckedChange = (id: string, checked: boolean | string) => {
form.setValue( form.setValue(
"output", "output",
checked ? [...output, id] : output.filter((value) => value !== id) checked ? [...(output ?? []), id] : (output ?? []).filter((value) => value !== id)
); );
}; };
@ -318,11 +318,11 @@ export default function DetailDaily() {
const handleUnitCheckedChange = (id: string, checked: boolean | string) => { const handleUnitCheckedChange = (id: string, checked: boolean | string) => {
if (checked) { if (checked) {
form.setValue("unit", [...unit, id]); form.setValue("unit", [...(unit ?? []), id]);
} else { } else {
if (id == "2") { if (id == "2") {
const temp = []; const temp = [];
for (const element of unit) { for (const element of unit ?? []) {
if (element == "1") { if (element == "1") {
temp.push("1"); temp.push("1");
} }
@ -331,7 +331,7 @@ export default function DetailDaily() {
} else { } else {
form.setValue( form.setValue(
"unit", "unit",
unit.filter((value) => value !== id) (unit ?? []).filter((value) => value !== id)
); );
} }
} }
@ -542,14 +542,14 @@ export default function DetailDaily() {
id={list.id} id={list.id}
name={`all${list.id}`} name={`all${list.id}`}
checked={ checked={
unit.includes("2") unit?.includes("2") ?? false
? true ? true
: !!selected[list.id] : !!selected[list.id]
} }
onCheckedChange={() => onCheckedChange={() =>
handleParentChange(list.id) handleParentChange(list.id)
} }
disabled={unit.includes("2")} disabled={unit?.includes("2") ?? false}
/> />
<label <label
htmlFor={list.name} htmlFor={list.name}
@ -564,7 +564,7 @@ export default function DetailDaily() {
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selectAll[list.id] : !!selectAll[list.id]
} }
@ -574,7 +574,7 @@ export default function DetailDaily() {
Boolean(e) Boolean(e)
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor="all-polres" htmlFor="all-polres"
@ -592,7 +592,7 @@ export default function DetailDaily() {
<Checkbox <Checkbox
id={`${list.id}${subDes.id}`} id={`${list.id}${subDes.id}`}
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selected[ : !!selected[
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
@ -603,7 +603,7 @@ export default function DetailDaily() {
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor={`${list.id}${subDes.id}`} htmlFor={`${list.id}${subDes.id}`}

View File

@ -294,11 +294,11 @@ export default function EditDaily() {
const output = form.watch("output"); const output = form.watch("output");
const isAllChecked = items.every((item) => output?.includes(item.id)); const isAllChecked = output && items.every((item) => output.includes(item.id));
const unit = form.watch("unit"); const unit = form.watch("unit");
const isAllUnitChecked = units.every((item) => unit?.includes(item.id)); const isAllUnitChecked = unit && units.every((item) => unit.includes(item.id));
const handleAllCheckedChange = (checked: boolean | string) => { const handleAllCheckedChange = (checked: boolean | string) => {
if (checked) { if (checked) {
@ -314,7 +314,7 @@ export default function EditDaily() {
const handleItemCheckedChange = (id: string, checked: boolean | string) => { const handleItemCheckedChange = (id: string, checked: boolean | string) => {
form.setValue( form.setValue(
"output", "output",
checked ? [...output, id] : output.filter((value) => value !== id) checked ? [...(output ?? []), id] : (output ?? []).filter((value) => value !== id)
); );
}; };
@ -331,11 +331,11 @@ export default function EditDaily() {
const handleUnitCheckedChange = (id: string, checked: boolean | string) => { const handleUnitCheckedChange = (id: string, checked: boolean | string) => {
if (checked) { if (checked) {
form.setValue("unit", [...unit, id]); form.setValue("unit", [...(unit ?? []), id]);
} else { } else {
if (id == "2") { if (id == "2") {
const temp = []; const temp = [];
for (const element of unit) { for (const element of unit ?? []) {
if (element == "1") { if (element == "1") {
temp.push("1"); temp.push("1");
} }
@ -344,7 +344,7 @@ export default function EditDaily() {
} else { } else {
form.setValue( form.setValue(
"unit", "unit",
unit.filter((value) => value !== id) (unit ?? []).filter((value) => value !== id)
); );
} }
} }
@ -506,7 +506,7 @@ export default function EditDaily() {
<Checkbox <Checkbox
checked={unit?.includes(item.id)} checked={unit?.includes(item.id)}
disabled={ disabled={
item.id === "3" && !unit.includes("2") item.id === "3" && !(unit?.includes("2") ?? false)
} }
onCheckedChange={(checked) => onCheckedChange={(checked) =>
handleUnitCheckedChange(item.id, checked) handleUnitCheckedChange(item.id, checked)
@ -550,14 +550,14 @@ export default function EditDaily() {
id={list.id} id={list.id}
name={`all${list.id}`} name={`all${list.id}`}
checked={ checked={
unit.includes("2") unit?.includes("2") ?? false
? true ? true
: !!selected[list.id] : !!selected[list.id]
} }
onCheckedChange={() => onCheckedChange={() =>
handleParentChange(list.id) handleParentChange(list.id)
} }
disabled={unit.includes("2")} disabled={unit?.includes("2") ?? false}
/> />
<label <label
htmlFor={list.name} htmlFor={list.name}
@ -572,7 +572,7 @@ export default function EditDaily() {
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selectAll[list.id] : !!selectAll[list.id]
} }
@ -582,7 +582,7 @@ export default function EditDaily() {
Boolean(e) Boolean(e)
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor="all-polres" htmlFor="all-polres"
@ -600,7 +600,7 @@ export default function EditDaily() {
<Checkbox <Checkbox
id={`${list.id}${subDes.id}`} id={`${list.id}${subDes.id}`}
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selected[ : !!selected[
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
@ -611,7 +611,7 @@ export default function EditDaily() {
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor={`${list.id}${subDes.id}`} htmlFor={`${list.id}${subDes.id}`}

View File

@ -242,11 +242,11 @@ export default function CreateDaily() {
const output = form.watch("output"); const output = form.watch("output");
const isAllChecked = items.every((item) => output?.includes(item.id)); const isAllChecked = output && items.every((item) => output.includes(item.id));
const unit = form.watch("unit"); const unit = form.watch("unit");
const isAllUnitChecked = units.every((item) => unit?.includes(item.id)); const isAllUnitChecked = unit && units.every((item) => unit.includes(item.id));
const handleAllCheckedChange = (checked: boolean | string) => { const handleAllCheckedChange = (checked: boolean | string) => {
if (checked) { if (checked) {
@ -262,7 +262,7 @@ export default function CreateDaily() {
const handleItemCheckedChange = (id: string, checked: boolean | string) => { const handleItemCheckedChange = (id: string, checked: boolean | string) => {
form.setValue( form.setValue(
"output", "output",
checked ? [...output, id] : output.filter((value) => value !== id) checked ? [...(output ?? []), id] : (output ?? []).filter((value) => value !== id)
); );
}; };
@ -279,11 +279,11 @@ export default function CreateDaily() {
const handleUnitCheckedChange = (id: string, checked: boolean | string) => { const handleUnitCheckedChange = (id: string, checked: boolean | string) => {
if (checked) { if (checked) {
form.setValue("unit", [...unit, id]); form.setValue("unit", [...(unit ?? []), id]);
} else { } else {
if (id == "2") { if (id == "2") {
const temp = []; const temp = [];
for (const element of unit) { for (const element of unit ?? []) {
if (element == "1") { if (element == "1") {
temp.push("1"); temp.push("1");
} }
@ -292,7 +292,7 @@ export default function CreateDaily() {
} else { } else {
form.setValue( form.setValue(
"unit", "unit",
unit.filter((value) => value !== id) (unit ?? []).filter((value) => value !== id)
); );
} }
} }
@ -472,7 +472,7 @@ export default function CreateDaily() {
<Checkbox <Checkbox
checked={unit?.includes(item.id)} checked={unit?.includes(item.id)}
disabled={ disabled={
item.id === "3" && !unit.includes("2") item.id === "3" && !(unit?.includes("2") ?? false)
} }
onCheckedChange={(checked) => onCheckedChange={(checked) =>
handleUnitCheckedChange(item.id, checked) handleUnitCheckedChange(item.id, checked)
@ -516,14 +516,14 @@ export default function CreateDaily() {
id={list.id} id={list.id}
name={`all${list.id}`} name={`all${list.id}`}
checked={ checked={
unit.includes("2") unit?.includes("2") ?? false
? true ? true
: !!selected[list.id] : !!selected[list.id]
} }
onCheckedChange={() => onCheckedChange={() =>
handleParentChange(list.id) handleParentChange(list.id)
} }
disabled={unit.includes("2")} disabled={unit?.includes("2") ?? false}
/> />
<label <label
htmlFor={list.name} htmlFor={list.name}
@ -538,7 +538,7 @@ export default function CreateDaily() {
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selectAll[list.id] : !!selectAll[list.id]
} }
@ -548,7 +548,7 @@ export default function CreateDaily() {
Boolean(e) Boolean(e)
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor="all-polres" htmlFor="all-polres"
@ -566,7 +566,7 @@ export default function CreateDaily() {
<Checkbox <Checkbox
id={`${list.id}${subDes.id}`} id={`${list.id}${subDes.id}`}
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selected[ : !!selected[
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
@ -577,7 +577,7 @@ export default function CreateDaily() {
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor={`${list.id}${subDes.id}`} htmlFor={`${list.id}${subDes.id}`}

View File

@ -281,11 +281,11 @@ export default function DetailDaily() {
const output = form.watch("output"); const output = form.watch("output");
const isAllChecked = items.every((item) => output?.includes(item.id)); const isAllChecked = output && items.every((item) => output.includes(item.id));
const unit = form.watch("unit"); const unit = form.watch("unit");
const isAllUnitChecked = units.every((item) => unit?.includes(item.id)); const isAllUnitChecked = unit && units.every((item) => unit.includes(item.id));
const handleAllCheckedChange = (checked: boolean | string) => { const handleAllCheckedChange = (checked: boolean | string) => {
if (checked) { if (checked) {
@ -301,7 +301,7 @@ export default function DetailDaily() {
const handleItemCheckedChange = (id: string, checked: boolean | string) => { const handleItemCheckedChange = (id: string, checked: boolean | string) => {
form.setValue( form.setValue(
"output", "output",
checked ? [...output, id] : output.filter((value) => value !== id) checked ? [...(output ?? []), id] : (output ?? []).filter((value) => value !== id)
); );
}; };
@ -318,11 +318,11 @@ export default function DetailDaily() {
const handleUnitCheckedChange = (id: string, checked: boolean | string) => { const handleUnitCheckedChange = (id: string, checked: boolean | string) => {
if (checked) { if (checked) {
form.setValue("unit", [...unit, id]); form.setValue("unit", [...(unit ?? []), id]);
} else { } else {
if (id == "2") { if (id == "2") {
const temp = []; const temp = [];
for (const element of unit) { for (const element of unit ?? []) {
if (element == "1") { if (element == "1") {
temp.push("1"); temp.push("1");
} }
@ -331,7 +331,7 @@ export default function DetailDaily() {
} else { } else {
form.setValue( form.setValue(
"unit", "unit",
unit.filter((value) => value !== id) (unit ?? []).filter((value) => value !== id)
); );
} }
} }
@ -542,14 +542,14 @@ export default function DetailDaily() {
id={list.id} id={list.id}
name={`all${list.id}`} name={`all${list.id}`}
checked={ checked={
unit.includes("2") unit?.includes("2") ?? false
? true ? true
: !!selected[list.id] : !!selected[list.id]
} }
onCheckedChange={() => onCheckedChange={() =>
handleParentChange(list.id) handleParentChange(list.id)
} }
disabled={unit.includes("2")} disabled={unit?.includes("2") ?? false}
/> />
<label <label
htmlFor={list.name} htmlFor={list.name}
@ -564,7 +564,7 @@ export default function DetailDaily() {
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selectAll[list.id] : !!selectAll[list.id]
} }
@ -574,7 +574,7 @@ export default function DetailDaily() {
Boolean(e) Boolean(e)
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor="all-polres" htmlFor="all-polres"
@ -592,7 +592,7 @@ export default function DetailDaily() {
<Checkbox <Checkbox
id={`${list.id}${subDes.id}`} id={`${list.id}${subDes.id}`}
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selected[ : !!selected[
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
@ -603,7 +603,7 @@ export default function DetailDaily() {
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor={`${list.id}${subDes.id}`} htmlFor={`${list.id}${subDes.id}`}

View File

@ -294,11 +294,11 @@ export default function EditDaily() {
const output = form.watch("output"); const output = form.watch("output");
const isAllChecked = items.every((item) => output?.includes(item.id)); const isAllChecked = output && items.every((item) => output.includes(item.id));
const unit = form.watch("unit"); const unit = form.watch("unit");
const isAllUnitChecked = units.every((item) => unit?.includes(item.id)); const isAllUnitChecked = unit && units.every((item) => unit.includes(item.id));
const handleAllCheckedChange = (checked: boolean | string) => { const handleAllCheckedChange = (checked: boolean | string) => {
if (checked) { if (checked) {
@ -314,7 +314,7 @@ export default function EditDaily() {
const handleItemCheckedChange = (id: string, checked: boolean | string) => { const handleItemCheckedChange = (id: string, checked: boolean | string) => {
form.setValue( form.setValue(
"output", "output",
checked ? [...output, id] : output.filter((value) => value !== id) checked ? [...(output ?? []), id] : (output ?? []).filter((value) => value !== id)
); );
}; };
@ -331,11 +331,11 @@ export default function EditDaily() {
const handleUnitCheckedChange = (id: string, checked: boolean | string) => { const handleUnitCheckedChange = (id: string, checked: boolean | string) => {
if (checked) { if (checked) {
form.setValue("unit", [...unit, id]); form.setValue("unit", [...(unit ?? []), id]);
} else { } else {
if (id == "2") { if (id == "2") {
const temp = []; const temp = [];
for (const element of unit) { for (const element of unit ?? []) {
if (element == "1") { if (element == "1") {
temp.push("1"); temp.push("1");
} }
@ -344,7 +344,7 @@ export default function EditDaily() {
} else { } else {
form.setValue( form.setValue(
"unit", "unit",
unit.filter((value) => value !== id) (unit ?? []).filter((value) => value !== id)
); );
} }
} }
@ -506,7 +506,7 @@ export default function EditDaily() {
<Checkbox <Checkbox
checked={unit?.includes(item.id)} checked={unit?.includes(item.id)}
disabled={ disabled={
item.id === "3" && !unit.includes("2") item.id === "3" && !(unit?.includes("2") ?? false)
} }
onCheckedChange={(checked) => onCheckedChange={(checked) =>
handleUnitCheckedChange(item.id, checked) handleUnitCheckedChange(item.id, checked)
@ -550,14 +550,14 @@ export default function EditDaily() {
id={list.id} id={list.id}
name={`all${list.id}`} name={`all${list.id}`}
checked={ checked={
unit.includes("2") unit?.includes("2") ?? false
? true ? true
: !!selected[list.id] : !!selected[list.id]
} }
onCheckedChange={() => onCheckedChange={() =>
handleParentChange(list.id) handleParentChange(list.id)
} }
disabled={unit.includes("2")} disabled={unit?.includes("2") ?? false}
/> />
<label <label
htmlFor={list.name} htmlFor={list.name}
@ -572,7 +572,7 @@ export default function EditDaily() {
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selectAll[list.id] : !!selectAll[list.id]
} }
@ -582,7 +582,7 @@ export default function EditDaily() {
Boolean(e) Boolean(e)
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor="all-polres" htmlFor="all-polres"
@ -600,7 +600,7 @@ export default function EditDaily() {
<Checkbox <Checkbox
id={`${list.id}${subDes.id}`} id={`${list.id}${subDes.id}`}
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selected[ : !!selected[
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
@ -611,7 +611,7 @@ export default function EditDaily() {
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor={`${list.id}${subDes.id}`} htmlFor={`${list.id}${subDes.id}`}

View File

@ -264,9 +264,9 @@ export default function CreateDaily() {
const media = form.watch("media"); const media = form.watch("media");
const unit = form.watch("unit"); const unit = form.watch("unit");
const isAllChecked = items.every((item) => output?.includes(item.id)); const isAllChecked = output && items.every((item) => output.includes(item.id));
const isAllMediaChecked = medias.every((item) => media?.includes(item.id)); const isAllMediaChecked = media && medias.every((item) => media.includes(item.id));
const isAllUnitChecked = units.every((item) => unit?.includes(item.id)); const isAllUnitChecked = unit && units.every((item) => unit.includes(item.id));
useEffect(() => { useEffect(() => {
async function initState() { async function initState() {
@ -398,10 +398,8 @@ export default function CreateDaily() {
form.setValue( form.setValue(
"output", "output",
checked checked
? [...output, item.id] ? [...(output ?? []), item.id]
: output.filter( : (output ?? []).filter((value) => value !== item.id)
(value) => value !== item.id
)
); );
}} }}
/> />
@ -464,16 +462,14 @@ export default function CreateDaily() {
checked={unit?.includes(item.id)} checked={unit?.includes(item.id)}
disabled={ disabled={
item.id === "polres" && item.id === "polres" &&
!unit.includes("polda") !(unit?.includes("polda") ?? false)
} }
onCheckedChange={(checked) => { onCheckedChange={(checked) => {
form.setValue( form.setValue(
"unit", "unit",
checked checked
? [...unit, item.id] ? [...(unit ?? []), item.id]
: unit.filter( : (unit ?? []).filter((value) => value !== item.id)
(value) => value !== item.id
)
); );
}} }}
/> />
@ -515,14 +511,14 @@ export default function CreateDaily() {
id={list.id} id={list.id}
name={`all${list.id}`} name={`all${list.id}`}
checked={ checked={
unit.includes("2") unit?.includes("2") ?? false
? true ? true
: !!selected[list.id] : !!selected[list.id]
} }
onCheckedChange={() => onCheckedChange={() =>
handleParentChange(list.id) handleParentChange(list.id)
} }
disabled={unit.includes("2")} disabled={unit?.includes("2") ?? false}
/> />
<label <label
htmlFor={list.name} htmlFor={list.name}
@ -537,7 +533,7 @@ export default function CreateDaily() {
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selectAll[list.id] : !!selectAll[list.id]
} }
@ -547,7 +543,7 @@ export default function CreateDaily() {
Boolean(e) Boolean(e)
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor="all-polres" htmlFor="all-polres"
@ -565,7 +561,7 @@ export default function CreateDaily() {
<Checkbox <Checkbox
id={`${list.id}${subDes.id}`} id={`${list.id}${subDes.id}`}
checked={ checked={
unit.includes("3") unit?.includes("3") ?? false
? true ? true
: !!selected[ : !!selected[
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
@ -576,7 +572,7 @@ export default function CreateDaily() {
`${list.id}${subDes.id}` `${list.id}${subDes.id}`
) )
} }
disabled={unit.includes("3")} disabled={unit?.includes("3") ?? false}
/> />
<label <label
htmlFor={`${list.id}${subDes.id}`} htmlFor={`${list.id}${subDes.id}`}
@ -648,8 +644,8 @@ export default function CreateDaily() {
form.setValue( form.setValue(
"media", "media",
checked checked
? [...media, item.id] ? [...(media ?? []), item.id]
: media.filter( : (media ?? []).filter(
(value) => value !== item.id (value) => value !== item.id
) )
); );

View File

@ -24,6 +24,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { import {
ChevronDown,
ChevronLeft, ChevronLeft,
ChevronRight, ChevronRight,
Eye, Eye,
@ -61,6 +62,7 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Label } from "@/components/ui/label";
type StatusFilter = string[]; type StatusFilter = string[];
@ -87,7 +89,8 @@ const ContentTable = () => {
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");
const [categories, setCategories] = React.useState<string[]>(); const [categories, setCategories] = React.useState<string[]>();
const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]); const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]);
const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]); // const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]);
const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
const [startDateString, setStartDateString] = React.useState<string>(""); const [startDateString, setStartDateString] = React.useState<string>("");
const [endDateString, setEndDateString] = React.useState<string>(""); const [endDateString, setEndDateString] = React.useState<string>("");
const [filterByCreator, setFilterByCreator] = React.useState<string>(""); const [filterByCreator, setFilterByCreator] = React.useState<string>("");
@ -168,6 +171,14 @@ const ContentTable = () => {
table.getColumn("judul")?.setFilterValue(e.target.value); table.getColumn("judul")?.setFilterValue(e.target.value);
}; };
function handleStatusCheckboxChange(value: any) {
setStatusFilter((prev: any) =>
prev.includes(value)
? prev.filter((status: any) => status !== value)
: [...prev, value]
);
}
return ( return (
<div className="w-full overflow-x-auto"> <div className="w-full overflow-x-auto">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between md:flex-row md:items-center md:justify-between lg:flex-row items-start lg:justify-between lg:items-center px-5"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between md:flex-row md:items-center md:justify-between lg:flex-row items-start lg:justify-between lg:items-center px-5">
@ -185,43 +196,88 @@ const ContentTable = () => {
/> />
</InputGroup> </InputGroup>
</div> </div>
<div className=" items-center gap-3 w-full md:w-[200px]"> <div className="flex flex-row gap-3">
{/* <Select <div className=" items-center gap-3 w-full md:w-[152px] border border-black rounded-lg">
onValueChange={(value) => { <Select
setStatusFilter([value]); onValueChange={(value) => {
}} setFileTypeFilter([value]);
> }}
<SelectTrigger className="w-[180px]"> >
<SelectValue placeholder="Select a Filter Status" /> <SelectTrigger className="w-full lg:w-[150px]">
</SelectTrigger> <SelectValue placeholder={t("selectFilter")} />
<SelectContent> </SelectTrigger>
<SelectGroup> <SelectContent>
<SelectLabel>Status</SelectLabel> <SelectGroup>
<SelectItem value="1">Menunggu Review</SelectItem> <SelectLabel>Filter</SelectLabel>
<SelectItem value="2">Diterima</SelectItem> <SelectItem value="1">{t("image")}</SelectItem>
<SelectItem value="3">Minta Update</SelectItem> <SelectItem value="2">{t("audio-visual")}</SelectItem>
<SelectItem value="4">Ditolak</SelectItem> <SelectItem value="3">{t("text")}</SelectItem>
</SelectGroup> <SelectItem value="4">{t("audio")}</SelectItem>
</SelectContent> </SelectGroup>
</Select> */} </SelectContent>
<Select </Select>
onValueChange={(value) => { </div>
setFileTypeFilter([value]); <DropdownMenu>
}} <DropdownMenuTrigger asChild>
> <Button variant="outline" className="ml-auto" size="md">
<SelectTrigger className="w-full lg:w-[180px]"> Filter <ChevronDown />
<SelectValue placeholder={t("selectFilter")} /> </Button>
</SelectTrigger> </DropdownMenuTrigger>
<SelectContent> <DropdownMenuContent
<SelectGroup> align="end"
<SelectLabel>Filter</SelectLabel> className="w-64 h-[150px] overflow-y-auto"
<SelectItem value="1">{t("image")}</SelectItem> >
<SelectItem value="2">{t("audio-visual")}</SelectItem> <Label className="ml-2 mt-2">Status</Label>
<SelectItem value="3">{t("text")}</SelectItem> <div className="flex items-center px-4 py-1">
<SelectItem value="4">Audio</SelectItem> <input
</SelectGroup> type="checkbox"
</SelectContent> id="status-2"
</Select> className="mr-2"
checked={statusFilter.includes(1)}
onChange={() => handleStatusCheckboxChange(1)}
/>
<label htmlFor="status-2" className="text-sm">
Menunggu Review
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-2"
className="mr-2"
checked={statusFilter.includes(2)}
onChange={() => handleStatusCheckboxChange(2)}
/>
<label htmlFor="status-2" className="text-sm">
Diterima
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-3"
className="mr-2"
checked={statusFilter.includes(3)}
onChange={() => handleStatusCheckboxChange(3)}
/>
<label htmlFor="status-3" className="text-sm">
Minta Update
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-4"
className="mr-2"
checked={statusFilter.includes(4)}
onChange={() => handleStatusCheckboxChange(4)}
/>
<label htmlFor="status-4" className="text-sm">
Ditolak
</label>
</div>
</DropdownMenuContent>
</DropdownMenu>
</div> </div>
</div> </div>
<Table className="overflow-hidden mt-3"> <Table className="overflow-hidden mt-3">

View File

@ -81,8 +81,8 @@ export default function CreateSpvFAQModal() {
}); });
const target = form.watch("publishTo"); const target = form.watch("publishTo");
const isAllTargetChecked = publishToList.every((item) => const isAllTargetChecked = target && publishToList.every((item) =>
target?.includes(item.id) target.includes(item.id)
); );
const onSubmit = async (data: z.infer<typeof FormSchema>) => { const onSubmit = async (data: z.infer<typeof FormSchema>) => {

View File

@ -98,7 +98,6 @@ export default function FilterPage() {
setSearchTitle(title); setSearchTitle(title);
setCategoryFilter(category ? category.split("&") : []); setCategoryFilter(category ? category.split("&") : []);
setSortByOpt(sortBy === "popular" ? "clickCount" : "createdAt"); setSortByOpt(sortBy === "popular" ? "clickCount" : "createdAt");
}, [searchParams]); }, [searchParams]);
useEffect(() => { useEffect(() => {
@ -120,7 +119,7 @@ export default function FilterPage() {
"", "",
isInt, isInt,
pageNumber pageNumber
); );
const content = response?.data?.data?.content || []; const content = response?.data?.data?.content || [];
const total = response?.data?.data?.totalPages || 1; const total = response?.data?.data?.totalPages || 1;
@ -437,10 +436,21 @@ export default function FilterPage() {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableContent", <p>
{ defaultValue: "Downloadable ContentS" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
)}`}</p> "downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}

View File

@ -486,10 +486,27 @@ const FilterPage = () => {
<div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black"> <div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
<p> <p>
{" "} {" "}
Audio {">"} <span className="font-bold">{t("allAudio", { defaultValue: "All Audio" })}</span> Audio {">"}{" "}
<span className="font-bold">
{t("allAudio", { defaultValue: "All Audio" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableAudio", { defaultValue: "Downloadable Audio" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -529,7 +546,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -547,7 +566,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("searchDate", { defaultValue: "Search Date" })} placeholderText={t("searchDate", {
defaultValue: "Search Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -707,14 +728,20 @@ const FilterPage = () => {
<div className="w-full pr-4 lg:pr-16 pb-4"> <div className="w-full pr-4 lg:pr-16 pb-4">
<Reveal> <Reveal>
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })} </h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}{" "}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -502,10 +502,27 @@ const FilterPage = () => {
<div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black"> <div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
<p> <p>
{" "} {" "}
{t("text", { defaultValue: "Text" })} {">"} <span className="font-bold">{t("allText", { defaultValue: "All Text" })}</span> {t("text", { defaultValue: "Text" })} {">"}{" "}
<span className="font-bold">
{t("allText", { defaultValue: "All Text" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableText", { defaultValue: "Downloadable Text" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -545,7 +562,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -563,7 +582,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("selectDate", { defaultValue: "Select Date" })} placeholderText={t("selectDate", {
defaultValue: "Select Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -769,14 +790,20 @@ const FilterPage = () => {
<Reveal> <Reveal>
<div className="flex-1"> <div className="flex-1">
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })}</h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -503,10 +503,26 @@ const FilterPage = () => {
<p> {t("image", { defaultValue: "Image" })}</p> <p> {t("image", { defaultValue: "Image" })}</p>
{">"} {">"}
<p> <p>
<span className="font-bold">{t("allImage", { defaultValue: "All Image" })}</span> <span className="font-bold">
{t("allImage", { defaultValue: "All Image" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableImage", { defaultValue: "Downloadable Image" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -542,7 +558,9 @@ const FilterPage = () => {
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
type="text" type="text"
id="search" id="search"
placeholder={t("searchTitle", { defaultValue: "Search Title" })} placeholder={t("searchTitle", {
defaultValue: "Search Title",
})}
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
/> />
</div> </div>
@ -556,7 +574,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -574,7 +594,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("selectDate", { defaultValue: "Select Date" })} placeholderText={t("selectDate", {
defaultValue: "Select Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -753,14 +775,20 @@ const FilterPage = () => {
<Reveal> <Reveal>
<div className="w-full"> <div className="w-full">
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })}</h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -499,10 +499,27 @@ const FilterPage = () => {
<p> <p>
{" "} {" "}
{t("video", { defaultValue: "Video" })}&nbsp; {t("video", { defaultValue: "Video" })}&nbsp;
{">"} <span className="font-bold">{t("allVideo", { defaultValue: "All Video" })}</span> {">"}{" "}
<span className="font-bold">
{t("allVideo", { defaultValue: "All Video" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableVideo", { defaultValue: "Downloadable Video" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -542,7 +559,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -560,7 +579,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("selectDate", { defaultValue: "Select Date" })} placeholderText={t("selectDate", {
defaultValue: "Select Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -766,14 +787,20 @@ const FilterPage = () => {
<Reveal> <Reveal>
<div className="w-full"> <div className="w-full">
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })}</h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -319,7 +319,7 @@ const FilterPage = () => {
} }
} }
const handleCategoryFilter = (e: boolean, id: string) => { const handleCategoryFilter = (e: boolean, id: string) => {
let filter = [...categoryFilter]; let filter = [...categoryFilter];
if (e) { if (e) {
@ -486,10 +486,27 @@ const FilterPage = () => {
<div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black"> <div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
<p> <p>
{" "} {" "}
Audio {">"} <span className="font-bold">{t("allAudio", { defaultValue: "All Audio" })}</span> Audio {">"}{" "}
<span className="font-bold">
{t("allAudio", { defaultValue: "All Audio" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableAudio", { defaultValue: "Downloadable Audio" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -529,7 +546,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -547,7 +566,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("searchDate", { defaultValue: "Search Date" })} placeholderText={t("searchDate", {
defaultValue: "Search Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -707,14 +728,20 @@ const FilterPage = () => {
<div className="w-full pr-4 lg:pr-16 pb-4"> <div className="w-full pr-4 lg:pr-16 pb-4">
<Reveal> <Reveal>
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })} </h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}{" "}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -492,10 +492,27 @@ const FilterPage = () => {
<div className="flex flex-row md:flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black"> <div className="flex flex-row md:flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
<p> <p>
{" "} {" "}
{t("text", { defaultValue: "Text" })} {">"} <span className="font-bold">{t("allText", { defaultValue: "All Text" })}</span> {t("text", { defaultValue: "Text" })} {">"}{" "}
<span className="font-bold">
{t("allText", { defaultValue: "All Text" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableText", { defaultValue: "Downloadable Text" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -535,7 +552,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -553,7 +572,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("selectDate", { defaultValue: "Select Date" })} placeholderText={t("selectDate", {
defaultValue: "Select Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -759,14 +780,20 @@ const FilterPage = () => {
<Reveal> <Reveal>
<div className="flex-1"> <div className="flex-1">
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })}</h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -303,7 +303,7 @@ const FilterPage = () => {
} }
} }
const handleCategoryFilter = (e: boolean, id: string) => { const handleCategoryFilter = (e: boolean, id: string) => {
let filter = [...categoryFilter]; let filter = [...categoryFilter];
if (e) { if (e) {
@ -469,10 +469,27 @@ const FilterPage = () => {
<div className="flex flex-row md:flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black"> <div className="flex flex-row md:flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
<p> <p>
{" "} {" "}
{t("image", { defaultValue: "Image" })} {">"} <span className="font-bold">{t("allImage", { defaultValue: "All Image" })}</span> {t("image", { defaultValue: "Image" })} {">"}{" "}
<span className="font-bold">
{t("allImage", { defaultValue: "All Image" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableImage", { defaultValue: "Downloadable Image" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -507,7 +524,9 @@ const FilterPage = () => {
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
type="text" type="text"
id="search" id="search"
placeholder={t("searchTitle", { defaultValue: "Search Title" })} placeholder={t("searchTitle", {
defaultValue: "Search Title",
})}
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
/> />
</div> </div>
@ -521,7 +540,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -539,7 +560,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("selectDate", { defaultValue: "Select Date" })} placeholderText={t("selectDate", {
defaultValue: "Select Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -718,14 +741,20 @@ const FilterPage = () => {
<Reveal> <Reveal>
<div className="flex-1"> <div className="flex-1">
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })}</h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -487,10 +487,27 @@ const FilterPage = () => {
<p> <p>
{" "} {" "}
{t("video", { defaultValue: "Video" })}&nbsp; {t("video", { defaultValue: "Video" })}&nbsp;
{">"} <span className="font-bold">{t("allVideo", { defaultValue: "All Video" })}</span> {">"}{" "}
<span className="font-bold">
{t("allVideo", { defaultValue: "All Video" })}
</span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t("downloadableVideo", { defaultValue: "Downloadable Video" })}`}</p> {!title ? (
<p>
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
"downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -530,7 +547,9 @@ const FilterPage = () => {
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
onChange={(date) => setMonthYearFilter(date)} onChange={(date) => setMonthYearFilter(date)}
dateFormat="MM | yyyy" dateFormat="MM | yyyy"
placeholderText={t("selectYear", { defaultValue: "Select Year" })} placeholderText={t("selectYear", {
defaultValue: "Select Year",
})}
showMonthYearPicker showMonthYearPicker
/> />
</div> </div>
@ -548,7 +567,9 @@ const FilterPage = () => {
onChange={(update) => { onChange={(update) => {
setDateRange(update); setDateRange(update);
}} }}
placeholderText={t("selectDate", { defaultValue: "Select Date" })} placeholderText={t("selectDate", {
defaultValue: "Select Date",
})}
onCalendarClose={() => setCalenderState(!calenderState)} onCalendarClose={() => setCalenderState(!calenderState)}
/> />
<div className="flex items-center"> <div className="flex items-center">
@ -754,14 +775,20 @@ const FilterPage = () => {
<Reveal> <Reveal>
<div className="flex-1"> <div className="flex-1">
<div className="flex flex-col items-end mb-4"> <div className="flex flex-col items-end mb-4">
<h2 className="text-lg font-semibold">{t("sortBy", { defaultValue: "Sort By" })}</h2> <h2 className="text-lg font-semibold">
{t("sortBy", { defaultValue: "Sort By" })}
</h2>
<select <select
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
onChange={(e) => handleSorting(e)} onChange={(e) => handleSorting(e)}
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
> >
<option value="latest">{t("latest", { defaultValue: "Latest" })}</option> <option value="latest">
<option value="popular">{t("mostPopular", { defaultValue: "Most Popular" })}</option> {t("latest", { defaultValue: "Latest" })}
</option>
<option value="popular">
{t("mostPopular", { defaultValue: "Most Popular" })}
</option>
</select> </select>
</div> </div>

View File

@ -30,6 +30,7 @@ import FilterVideoComponent from "@/components/landing-page/filter-all/video-fil
import FilterDocumentComponent from "@/components/landing-page/filter-all/document-filter-card"; import FilterDocumentComponent from "@/components/landing-page/filter-all/document-filter-card";
import FilterAudioComponent from "@/components/landing-page/filter-all/audio-filter-card"; import FilterAudioComponent from "@/components/landing-page/filter-all/audio-filter-card";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import FilterIndeksComponent from "@/components/landing-page/filter-all/indeks-filter-card";
export default function FilterPage() { export default function FilterPage() {
const router = useRouter(); const router = useRouter();
@ -98,7 +99,6 @@ export default function FilterPage() {
setSearchTitle(title); setSearchTitle(title);
setCategoryFilter(category ? category.split("&") : []); setCategoryFilter(category ? category.split("&") : []);
setSortByOpt(sortBy === "popular" ? "clickCount" : "createdAt"); setSortByOpt(sortBy === "popular" ? "clickCount" : "createdAt");
}, [searchParams]); }, [searchParams]);
useEffect(() => { useEffect(() => {
@ -120,7 +120,7 @@ export default function FilterPage() {
"", "",
isInt, isInt,
pageNumber pageNumber
); );
const content = response?.data?.data?.content || []; const content = response?.data?.data?.content || [];
const total = response?.data?.data?.totalPages || 1; const total = response?.data?.data?.totalPages || 1;
@ -437,10 +437,21 @@ export default function FilterPage() {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableContent", <p>
{ defaultValue: "Downloadable ContentS" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
)}`}</p> "downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}
@ -734,6 +745,13 @@ export default function FilterPage() {
endDateString={endDateString} endDateString={endDateString}
monthYearFilter={monthYearFilter} monthYearFilter={monthYearFilter}
/> />
<FilterIndeksComponent
categoryFilter={categoryFilter}
sortByOpt={sortByOpt}
startDateString={startDateString}
endDateString={endDateString}
monthYearFilter={monthYearFilter}
/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -494,10 +494,21 @@ const FilterPage = () => {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableAudio", <p>
{ defaultValue: "Downloadable Audio" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
)}`}</p> "downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}

View File

@ -510,10 +510,21 @@ const FilterPage = () => {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableText", <p>
{ defaultValue: "Downloadable Text" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
)}`}</p> "downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}

View File

@ -516,10 +516,21 @@ const FilterPage = () => {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableImage", <p>
{ defaultValue: "Downloadable Image" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
)}`}</p> "downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4"> <div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">

View File

@ -425,10 +425,22 @@ export default function FilterPage() {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableContent", <p>
{ defaultValue: "Downloadable ContentS" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${
)}`}</p> totalContent ?? 0
} ${t("downloadableImage", {
defaultValue: "artikel berisi Foto yang dapat diunduh",
})}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}

View File

@ -511,10 +511,21 @@ const FilterPage = () => {
</span> </span>
</p> </p>
<p className="font-bold">|</p> <p className="font-bold">|</p>
<p>{`${t("thereIs", { defaultValue: "There Is" })} ${totalContent} ${t( {!title ? (
"downloadableVideo", <p>
{ defaultValue: "Downloadable Video" } {`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
)}`}</p> "downloadableImage",
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
)}`}
</p>
) : (
<>
<p>
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
<span className="font-bold">"{title}"</span>
</p>
</>
)}
</div> </div>
{/* Left */} {/* Left */}

View File

@ -570,6 +570,7 @@ export default function FormAudioUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"
@ -668,7 +669,9 @@ export default function FormAudioUpdate() {
<div className="flex flex-col lg:flex-row gap-10"> <div className="flex flex-col lg:flex-row gap-10">
<Card className="w-full lg:w-8/12"> <Card className="w-full lg:w-8/12">
<div className="px-6 py-6"> <div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">{t("form-audio", { defaultValue: "Form Audio" })}</p> <p className="text-lg font-semibold mb-3">
{t("form-audio", { defaultValue: "Form Audio" })}
</p>
<div className="gap-5 mb-5"> <div className="gap-5 mb-5">
{/* Input Title */} {/* Input Title */}
<div className="space-y-2 py-3"> <div className="space-y-2 py-3">
@ -707,14 +710,18 @@ export default function FormAudioUpdate() {
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{/* Show the category from details if it doesn't exist in categories list */} {/* Show the category from details if it doesn't exist in categories list */}
{detail && !categories.find(cat => String(cat.id) === String(detail.category.id)) && ( {detail &&
<SelectItem !categories.find(
key={String(detail.category.id)} (cat) =>
value={String(detail.category.id)} String(cat.id) === String(detail.category.id)
> ) && (
{detail.category.name} <SelectItem
</SelectItem> key={String(detail.category.id)}
)} value={String(detail.category.id)}
>
{detail.category.name}
</SelectItem>
)}
{categories.map((category) => ( {categories.map((category) => (
<SelectItem <SelectItem
key={String(category.id)} key={String(category.id)}
@ -730,7 +737,9 @@ export default function FormAudioUpdate() {
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description", { defaultValue: "Description" })}</Label> <Label>
{t("description", { defaultValue: "Description" })}
</Label>
<Controller <Controller
control={control} control={control}
name="description" name="description"
@ -745,7 +754,9 @@ export default function FormAudioUpdate() {
)} )}
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("select-file", { defaultValue: "Select File" })}</Label> <Label>
{t("select-file", { defaultValue: "Select File" })}
</Label>
{/* <Input {/* <Input
id="fileInput" id="fileInput"
type="file" type="file"
@ -761,7 +772,9 @@ export default function FormAudioUpdate() {
{t("drag-file", { defaultValue: "Drag File" })} {t("drag-file", { defaultValue: "Drag File" })}
</h4> </h4>
<div className=" text-xs text-muted-foreground"> <div className=" text-xs text-muted-foreground">
{t("upload-file-audio-max", { defaultValue: "Upload File Audio Max" })} {t("upload-file-audio-max", {
defaultValue: "Upload File Audio Max",
})}
</div> </div>
</div> </div>
</div> </div>
@ -1010,7 +1023,9 @@ export default function FormAudioUpdate() {
</div> </div>
<div className="px-3 py-3"> <div className="px-3 py-3">
<div className="flex flex-col gap-6 space-y-2"> <div className="flex flex-col gap-6 space-y-2">
<Label>{t("publish-target", { defaultValue: "Publish Target" })}</Label> <Label>
{t("publish-target", { defaultValue: "Publish Target" })}
</Label>
{options.map((option: Option) => ( {options.map((option: Option) => (
<div key={option.id} className="flex gap-2 items-center"> <div key={option.id} className="flex gap-2 items-center">
<Checkbox <Checkbox

View File

@ -548,6 +548,7 @@ export default function FormImageUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"

View File

@ -552,6 +552,7 @@ export default function FormTeksUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"
@ -624,7 +625,9 @@ export default function FormTeksUpdate() {
<div className="flex flex-col lg:flex-row gap-10"> <div className="flex flex-col lg:flex-row gap-10">
<Card className="w-full lg:w-8/12"> <Card className="w-full lg:w-8/12">
<div className="px-6 py-6"> <div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">{t("form-text", { defaultValue: "Form Text" })}</p> <p className="text-lg font-semibold mb-3">
{t("form-text", { defaultValue: "Form Text" })}
</p>
<div className="gap-5 mb-5"> <div className="gap-5 mb-5">
{/* Input Title */} {/* Input Title */}
<div className="space-y-2 py-3"> <div className="space-y-2 py-3">
@ -663,14 +666,18 @@ export default function FormTeksUpdate() {
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{/* Show the category from details if it doesn't exist in categories list */} {/* Show the category from details if it doesn't exist in categories list */}
{detail && !categories.find(cat => String(cat.id) === String(detail.category.id)) && ( {detail &&
<SelectItem !categories.find(
key={String(detail.category.id)} (cat) =>
value={String(detail.category.id)} String(cat.id) === String(detail.category.id)
> ) && (
{detail.category.name} <SelectItem
</SelectItem> key={String(detail.category.id)}
)} value={String(detail.category.id)}
>
{detail.category.name}
</SelectItem>
)}
{categories.map((category) => ( {categories.map((category) => (
<SelectItem <SelectItem
key={String(category.id)} key={String(category.id)}
@ -685,7 +692,9 @@ export default function FormTeksUpdate() {
</div> </div>
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description", { defaultValue: "Description" })}</Label> <Label>
{t("description", { defaultValue: "Description" })}
</Label>
<Controller <Controller
control={control} control={control}
name="description" name="description"
@ -700,7 +709,9 @@ export default function FormTeksUpdate() {
)} )}
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("select-file", { defaultValue: "Select File" })}</Label> <Label>
{t("select-file", { defaultValue: "Select File" })}
</Label>
{/* <Input {/* <Input
id="fileInput" id="fileInput"
type="file" type="file"
@ -716,7 +727,9 @@ export default function FormTeksUpdate() {
{t("drag-file", { defaultValue: "Drag File" })} {t("drag-file", { defaultValue: "Drag File" })}
</h4> </h4>
<div className=" text-xs text-muted-foreground"> <div className=" text-xs text-muted-foreground">
{t("upload-file-text-max", { defaultValue: "Upload File Text Max" })} {t("upload-file-text-max", {
defaultValue: "Upload File Text Max",
})}
</div> </div>
</div> </div>
</div> </div>
@ -725,7 +738,9 @@ export default function FormTeksUpdate() {
<div>{fileList}</div> <div>{fileList}</div>
<div className=" flex justify-between gap-2"> <div className=" flex justify-between gap-2">
<div className="flex flex-row items-center gap-3 py-3"> <div className="flex flex-row items-center gap-3 py-3">
<Label>{t("watermark", { defaultValue: "Watermark" })}</Label> <Label>
{t("watermark", { defaultValue: "Watermark" })}
</Label>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Switch defaultChecked color="primary" id="c2" /> <Switch defaultChecked color="primary" id="c2" />
</div> </div>
@ -765,7 +780,9 @@ export default function FormTeksUpdate() {
rel="noopener noreferrer" rel="noopener noreferrer"
className="text-blue-500 text-sm" className="text-blue-500 text-sm"
> >
{t("view-file", { defaultValue: "View File" })} {t("view-file", {
defaultValue: "View File",
})}
</a> </a>
</div> </div>
<div> <div>
@ -783,7 +800,9 @@ export default function FormTeksUpdate() {
} }
className="form-checkbox" className="form-checkbox"
/> />
<span>{t("all", { defaultValue: "All" })}</span> <span>
{t("all", { defaultValue: "All" })}
</span>
</Label> </Label>
</div> </div>
<div> <div>
@ -923,7 +942,9 @@ export default function FormTeksUpdate() {
</div> </div>
<div className="px-3 py-3"> <div className="px-3 py-3">
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
<Label>{t("publish-target", { defaultValue: "Publish Target" })}</Label> <Label>
{t("publish-target", { defaultValue: "Publish Target" })}
</Label>
{options.map((option) => ( {options.map((option) => (
<div key={option.id} className="flex gap-2 items-center"> <div key={option.id} className="flex gap-2 items-center">
<Checkbox <Checkbox
@ -944,7 +965,9 @@ export default function FormTeksUpdate() {
</div> </div>
<div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm"> <div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm">
<MailIcon /> <MailIcon />
<p className="">{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)</p> <p className="">
{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)
</p>
</div> </div>
<div className="px-3 py-3"> <div className="px-3 py-3">
<p>{t("information", { defaultValue: "Information" })}:</p> <p>{t("information", { defaultValue: "Information" })}:</p>

View File

@ -626,6 +626,7 @@ export default function FormVideoUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"

View File

@ -0,0 +1,241 @@
"use client";
import { useEffect, useState } from "react";
import { useSearchParams, useParams } from "next/navigation";
import Image from "next/image";
import Link from "next/link"; // pastikan path-nya sesuai
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
import { getIndeksData, getIndeksDataFilter } from "@/service/landing/landing";
import { usePathname, useRouter } from "@/i18n/routing";
import { loading } from "@/lib/swal";
import { getOnlyMonthAndYear } from "@/utils/globals";
export default function IndeksCarouselComponent(props: {
categoryFilter?: any;
sortByOpt?: string;
startDateString?: string;
endDateString?: string;
monthYearFilter?: any;
}) {
const {
categoryFilter,
sortByOpt,
startDateString,
endDateString,
monthYearFilter,
} = props;
const router = useRouter();
const asPath = usePathname();
const params = useParams();
const searchParams = useSearchParams();
const [indeksData, setIndeksData] = useState<any[]>([]); // ✅ State untuk menyimpan konten data
const [newContent, setNewContent] = useState<any[]>([]); // Optional, bisa jadi redundant
const [totalData, setTotalData] = useState<number>(0);
const [totalPage, setTotalPage] = useState<number>(0);
const [totalContent, setTotalContent] = useState<number>(0);
const sortBy = searchParams?.get("sortBy");
const title = searchParams?.get("title");
const categorie = searchParams?.get("category");
const group = searchParams?.get("group");
const poldaName = params?.polda_name;
const satkerName = params?.satker_name;
let prefixPath = poldaName
? `/polda/${poldaName}`
: satkerName
? `/satker/${satkerName}`
: "/";
// useEffect(() => {
// initFetch();
// }, []);
// const initFetch = async () => {
// try {
// const month =
// monthYearFilter?.split("/")?.[0]?.replace("0", "") || "";
// const year = monthYearFilter?.split("/")?.[1] || "";
// const name = title == undefined ? "" : title;
// const filterGroup = group == undefined ? asPath.split("/")[2] : group;
// const response = await getIndeksDataFilter(
// name,
// filter,
// 12,
// 0,
// sortByOpt,
// "",
// "",
// filterGroup,
// startDateString,
// endDateString,
// monthYearFilter
// ? getOnlyMonthAndYear(monthYearFilter)
// ?.split("/")[0]
// ?.replace("", "")
// : "",
// monthYearFilter
// ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
// : ""
// );
// const data = response?.data?.data;
// const contentData = data?.content;
// setIndeksData(contentData || []);
// setNewContent(contentData || []);
// setTotalData(data?.totalElements || 0);
// setTotalPage(data?.totalPages || 0);
// setTotalContent(data?.totalElements || 0);
// } catch (error) {
// console.error("Error fetching indeks data:", error);
// }
// };
useEffect(() => {
initFetch();
}, [
title,
categoryFilter,
categorie,
group,
startDateString,
endDateString,
monthYearFilter,
sortByOpt,
]);
async function initFetch() {
if (asPath?.includes("/polda/") == true) {
if (asPath?.split("/")[2] !== "[polda_name]") {
const filter =
categoryFilter?.length > 0
? categoryFilter?.sort().join(",")
: categorie || "";
const name = title == undefined ? "" : title;
const filterGroup = group == undefined ? asPath.split("/")[2] : group;
loading();
const response = await getIndeksDataFilter(
"4",
name,
filter,
12,
0,
sortByOpt,
"",
"",
filterGroup,
startDateString,
endDateString,
monthYearFilter
? getOnlyMonthAndYear(monthYearFilter)
?.split("/")[0]
?.replace("", "")
: "",
monthYearFilter
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
: ""
);
close();
const data = response?.data?.data;
const contentData = data?.content;
setNewContent(contentData);
setTotalData(data?.totalElements);
setTotalPage(data?.totalPages);
setTotalContent(response?.data?.data?.totalElements);
}
} else {
const filter =
categoryFilter?.length > 0
? categoryFilter?.sort().join(",")
: categorie || "";
const name = title == undefined ? "" : title;
loading();
const response = await getIndeksDataFilter(
"4",
name,
filter,
12,
0,
sortByOpt,
"",
"",
"",
startDateString,
endDateString,
monthYearFilter
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
: "",
monthYearFilter
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
: ""
);
close();
const data = response?.data?.data;
const contentData = data?.content;
setNewContent(contentData);
setTotalData(data?.totalElements);
setTotalPage(data?.totalPages);
setTotalContent(response?.data?.data?.totalElements);
}
}
return newContent?.length > 0 ? (
<div className="flex flex-col gap-3 w-full">
<p>{`Indeks (${totalContent})`}</p>
<Carousel className="w-full max-w-7xl mx-auto mt-3">
<CarouselContent>
{newContent.map((image: any) => (
<CarouselItem key={image?.id} className="md:basis-1/2 lg:basis-1/3">
<div
onClick={() => router.push(`/indeks/detail/${image?.slug}`)}
className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300"
>
<div className="w-full h-48 lg:h-60">
<Image
priority
width={2560}
height={1440}
alt="image"
src={image?.thumbnailLink}
className="w-full h-full object-cover"
/>
</div>
<div className="p-4 h-full flex flex-col justify-between">
<div className="flex flex-col gap-1 flex-grow">
<p className="text-[10px] font-bold text-[#bb3523] uppercase">
{image?.categoryName?.toUpperCase() ?? "Giat Pimpinan"}
</p>
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-4">
{image?.title}
</p>
</div>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious className="-ml-0" />
<CarouselNext className="-mr-0" />
</Carousel>
<div className="flex justify-center mt-1 mb-6">
<Link
href={`${prefixPath}/image`}
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
>
Lihat Semua
</Link>
</div>
</div>
) : null;
}

View File

@ -55,6 +55,7 @@ type HeroModalProps = {
group: string; group: string;
poldaName?: string; poldaName?: string;
satkerName?: string; satkerName?: string;
dataContent?: any;
}; };
const HeroModal = ({ const HeroModal = ({
@ -62,6 +63,7 @@ const HeroModal = ({
group, group,
poldaName, poldaName,
satkerName, satkerName,
dataContent,
}: HeroModalProps) => { }: HeroModalProps) => {
const [heroData, setHeroData] = useState<any[]>([]); const [heroData, setHeroData] = useState<any[]>([]);
const params = useParams(); const params = useParams();
@ -138,7 +140,7 @@ const HeroModal = ({
ref={modalRef} ref={modalRef}
className="relative dark:bg-gray-900 rounded-lg w-[90%] md:w-[600px] p-4 shadow-none" className="relative dark:bg-gray-900 rounded-lg w-[90%] md:w-[600px] p-4 shadow-none"
> >
{heroData?.length > 0 && ( {dataContent?.length > 0 && (
<> <>
<button <button
className="absolute left-3 top-1/2 z-10 -translate-y-1/2 text-white text-3xl" className="absolute left-3 top-1/2 z-10 -translate-y-1/2 text-white text-3xl"
@ -161,7 +163,7 @@ const HeroModal = ({
autoplay={{ delay: 3000 }} autoplay={{ delay: 3000 }}
className="mySwiper w-full" className="mySwiper w-full"
> >
{heroData.map((list: any) => ( {dataContent.map((list: any) => (
<SwiperSlide key={list?.id}> <SwiperSlide key={list?.id}>
<div className="relative h-[310px] lg:h-[420px]"> <div className="relative h-[310px] lg:h-[420px]">
<button <button
@ -437,6 +439,18 @@ const HeroNew = (props: { group?: string }) => {
? Buffer.from(str).toString("base64") ? Buffer.from(str).toString("base64")
: window.btoa(str); : window.btoa(str);
const [scrollIndex, setScrollIndex] = useState(0);
useEffect(() => {
if (!content || content.length < 3) return;
const interval = setInterval(() => {
setScrollIndex((prevIndex) => (prevIndex + 1) % content.length);
}, 3000);
return () => clearInterval(interval);
}, [content]);
return ( return (
<div className="flex items-start justify-center mx-auto w-auto"> <div className="flex items-start justify-center mx-auto w-auto">
<div className="relative"> <div className="relative">
@ -446,6 +460,7 @@ const HeroNew = (props: { group?: string }) => {
group={props.group || "mabes"} group={props.group || "mabes"}
poldaName={poldaName as string} poldaName={poldaName as string}
satkerName={satkerName as string} satkerName={satkerName as string}
dataContent={content}
/> />
)} )}
</div> </div>
@ -509,122 +524,142 @@ const HeroNew = (props: { group?: string }) => {
</Carousel> */} </Carousel> */}
<div className="relative w-full"> <div className="relative w-full">
<Swiper {content && content.length > 0 && (
modules={[Autoplay, Navigation]} <Swiper
autoplay={{ delay: 3000, disableOnInteraction: false }} modules={[Autoplay, Navigation]}
navigation={{ autoplay={{
nextEl: ".swiper-button-next", delay: 3000,
prevEl: ".swiper-button-prev", disableOnInteraction: false,
}} }}
loop loop={true}
className="w-full" navigation={{
> nextEl: ".swiper-button-next",
{content?.map((list: any) => ( prevEl: ".swiper-button-prev",
<SwiperSlide key={list?.id}> }}
<div className="relative h-[310px] lg:h-[700px]"> className="w-full"
{/* Gambar */} >
<Image {content.map((list: any) => (
priority <SwiperSlide key={list?.id}>
src={list?.smallThumbnailLink} <div className="relative h-[310px] lg:h-[700px]">
alt="gambar" {/* Gambar */}
fill <Image
className="object-cover w-full h-full" priority
/> src={list?.smallThumbnailLink}
alt="gambar"
fill
className="object-cover w-full h-full"
/>
{/* Overlay hitam transparan */} {/* Overlay */}
<div className="absolute inset-0 bg-black/40 z-10" /> <div className="absolute inset-0 bg-black/40 z-10" />
{/* Konten judul */} {/* Judul & Link */}
<Link <Link
href={ href={
Number(list?.fileTypeId) === 1 Number(list?.fileTypeId) === 1
? `${prefixPath}/image/detail/${list?.slug}` ? `${prefixPath}/image/detail/${list?.slug}`
: Number(list?.fileTypeId) === 2 : Number(list?.fileTypeId) === 2
? `${prefixPath}/video/detail/${list?.slug}` ? `${prefixPath}/video/detail/${list?.slug}`
: Number(list?.fileTypeId) === 3 : Number(list?.fileTypeId) === 3
? `${prefixPath}/document/detail/${list?.slug}` ? `${prefixPath}/document/detail/${list?.slug}`
: `${prefixPath}/audio/detail/${list?.slug}` : `${prefixPath}/audio/detail/${list?.slug}`
} }
className="absolute bottom-20 left-8 lg:left-32 z-20 text-white w-[85%] lg:w-[45%] cursor-pointer" className="absolute bottom-20 left-8 lg:left-32 z-20 text-white w-[85%] lg:w-[45%] cursor-pointer"
> >
<span className="text-red-600 text-lg font-bold uppercase"> <span className="text-red-600 text-lg font-bold uppercase">
{list?.categoryName} {list?.categoryName}
</span> </span>
<h2 className="text-xl font-bold">{list?.title}</h2> <h2 className="text-xl font-bold">{list?.title}</h2>
<p className="text-sm mt-2"> <p className="text-sm mt-2">
{formatDateToIndonesian(new Date(list?.createdAt))}{" "} {formatDateToIndonesian(new Date(list?.createdAt))}{" "}
{list?.timezone || "WIB"} | 👁 {list?.clickCount} {list?.timezone || "WIB"} | 👁 {list?.clickCount}
</p> </p>
</Link> </Link>
{/* Tombol navigasi */} {/* Tombol navigasi */}
<div className="swiper-button-prev absolute left-6 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full"> <div className="swiper-button-prev absolute left-6 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
<ChevronLeft className="w-5 h-5" /> <ChevronLeft className="w-5 h-5" />
</div>
<div className="swiper-button-next absolute right-6 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
<ChevronRight className="w-5 h-5" />
</div>
</div> </div>
<div className="swiper-button-next absolute right-6 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full"> </SwiperSlide>
<ChevronRight className="w-5 h-5" /> ))}
</div> </Swiper>
</div> )}
</SwiperSlide>
))}
</Swiper>
</div> </div>
<div className="hidden lg:flex flex-col gap-3 absolute bottom-4 right-[38px] w-[520px] bg-black/40 p-4 rounded-lg z-10"> <div className="hidden lg:flex flex-col gap-3 absolute bottom-4 right-[38px] w-[520px] bg-black/40 p-4 rounded-lg z-10 h-[250px] overflow-hidden">
{newContent?.slice(0, 3).map((item: any) => ( <div
<li key={item?.id} className="flex gap-4 flex-row lg:w-full mx-2"> className="transition-transform duration-500 ease-in-out"
<div className="flex-shrink-0 w-32 rounded-lg"> style={{
<Image transform: "translateY(0%)",
priority={true} }}
placeholder={`data:image/svg+xml;base64,${toBase64( key={scrollIndex}
shimmer(700, 475) >
)}`} {content?.length >= 2 &&
width={720} [0, 1].map((offset) => {
height={480} const item = content[(scrollIndex + offset) % content.length];
src={item?.smallThumbnailLink} return (
alt={item?.title} <li
className="w-full h-[100px] object-cover rounded-lg" key={item?.id}
/> className="flex gap-4 flex-row lg:w-full mx-2 mb-2"
</div> >
<div className="w-[280px] lg:w-full"> <div className="flex-shrink-0 w-32 rounded-lg">
<Link <Image
href={ priority={true}
Number(item?.fileTypeId) == 1 placeholder={`data:image/svg+xml;base64,${toBase64(
? `${prefixPath}/image/detail/${item?.slug}` shimmer(700, 475)
: Number(item?.fileTypeId) == 2 )}`}
? `${prefixPath}/video/detail/${item?.slug}` width={720}
: Number(item?.fileTypeId) == 3 height={480}
? `${prefixPath}/document/detail/${item?.slug}` src={item?.smallThumbnailLink}
: `${prefixPath}/audio/detail/${item?.slug}` alt={item?.title}
} className="w-full h-[100px] object-cover rounded-lg"
className="flex flex-col justify-between"
>
<p className="rounded-lg flex text-red-600 font-bold uppercase w-fit">
{item?.categoryName}
</p>
<h3 className="text-base text-white font-bold">
{item?.title}
</h3>
<p className="text-[10px] flex flex-row items-center gap-1 text-white mt-2">
{formatDateToIndonesian(new Date(item?.createdAt))}{" "}
{item?.timezone || "WIB"} |{" "}
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
/> />
</svg>{" "} </div>
{item?.clickCount} <div className="w-[280px] lg:w-full">
</p> <Link
</Link> href={
</div> Number(item?.fileTypeId) == 1
</li> ? `${prefixPath}/image/detail/${item?.slug}`
))} : Number(item?.fileTypeId) == 2
? `${prefixPath}/video/detail/${item?.slug}`
: Number(item?.fileTypeId) == 3
? `${prefixPath}/document/detail/${item?.slug}`
: `${prefixPath}/audio/detail/${item?.slug}`
}
className="flex flex-col justify-between"
>
<p className="rounded-lg flex text-red-600 font-bold uppercase w-fit">
{item?.categoryName}
</p>
<h3 className="text-base text-white font-bold">
{item?.title}
</h3>
<p className="text-[10px] flex flex-row items-center gap-1 text-white mt-2">
{formatDateToIndonesian(new Date(item?.createdAt))}{" "}
{item?.timezone || "WIB"} |{" "}
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
/>
</svg>{" "}
{item?.clickCount}
</p>
</Link>
</div>
</li>
);
})}
</div>
</div> </div>
</div> </div>
)} )}

View File

@ -480,7 +480,7 @@ const DetailVideo = () => {
className="cursor-pointer flex flex-col items-center gap-1" className="cursor-pointer flex flex-col items-center gap-1"
> >
<img <img
src={file?.thumbnailLink} src={file?.thumbnailFileUrl}
alt={file?.fileName} alt={file?.fileName}
className="w-32 h-20 object-cover rounded" className="w-32 h-20 object-cover rounded"
/> />

View File

@ -31,45 +31,43 @@ export default function LocalSwitcher() {
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const params = useParams(); const params = useParams();
const localActive = useLocale() || "in"; const locale = useLocale() || "in";
const [selectedLang, setSelectedLang] = useState<string>(""); const [selectedLang, setSelectedLang] = useState<string>("in");
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [hasInitialized, setHasInitialized] = useState(false);
useEffect(() => { useEffect(() => {
const storedLang = getLanguage(); const storedLang = getLanguage();
let joinParam = ""; let joinParam = "";
if (searchParams) { if (searchParams) {
joinParam = Array.from(searchParams.entries()) joinParam = Array.from(searchParams.entries())
.map(([key, value]) => `${key}=${value}`) .map(([key, value]) => `${key}=${value}`)
.join("&"); .join("&");
} }
if (pathname.includes("polda")) { const redirectTo = (lang: string) => {
startTransition(() => { startTransition(() => {
router.replace(pathname + joinParam === "" ? "" : `?${joinParam}`, { router.replace(pathname + (joinParam ? `?${joinParam}` : ""), {
locale: "in", locale: lang,
}); });
}); });
} else { };
if (!hasInitialized) {
if (!storedLang) { if (!storedLang) {
setLanguage("in"); setLanguage("in");
setSelectedLang("in"); setSelectedLang("in");
redirectTo("in");
startTransition(() => {
router.replace(pathname + joinParam === "" ? "" : `?${joinParam}`, {
locale: "in",
});
});
} else { } else {
setSelectedLang(storedLang); setSelectedLang(storedLang);
startTransition(() => { if (locale !== storedLang) {
router.replace(pathname + joinParam === "" ? "" : `?${joinParam}`, { redirectTo(storedLang);
locale: storedLang, }
});
});
} }
setHasInitialized(true);
} }
}, [searchParams]); }, []);
const onSelectChange = (nextLocale: string) => { const onSelectChange = (nextLocale: string) => {
setLanguage(nextLocale); setLanguage(nextLocale);

View File

@ -643,7 +643,7 @@
"FilterPage": { "FilterPage": {
"downloadableContent": "Downloadable Content", "downloadableContent": "Downloadable Content",
"content": "Content", "content": "Content",
"allContent":"All Content", "allContent": "All Content",
"image": "Image", "image": "Image",
"video": "Video", "video": "Video",
"text": "Text", "text": "Text",
@ -666,7 +666,8 @@
"categories": "Categories", "categories": "Categories",
"sortBy": "Sort by", "sortBy": "Sort by",
"latest": "Latest", "latest": "Latest",
"mostPopular": "Most Popular" "mostPopular": "Most Popular",
"search-results": "Search Result"
}, },
"Planning": { "Planning": {
"planning": "Planning", "planning": "Planning",

View File

@ -667,7 +667,8 @@
"categories": "Kategori", "categories": "Kategori",
"sortBy": "Urutkan Berdasarkan", "sortBy": "Urutkan Berdasarkan",
"latest": "Terbaru", "latest": "Terbaru",
"mostPopular": "Terpopuler" "mostPopular": "Terpopuler",
"search-results": "Hasil Pencarian"
}, },
"Planning": { "Planning": {
"planning": "Perencanaan", "planning": "Perencanaan",

19279
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build --no-lint",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"test": "jest", "test": "jest",

View File

@ -43,3 +43,8 @@ export async function getBlogCategory() {
const url = "blog/categories/enable"; const url = "blog/categories/enable";
return httpGetInterceptor(url); return httpGetInterceptor(url);
} }
export async function publicListBlog(page: any, limit: any) {
const url = `blog/public/pagination?enablePage=1&page=${page}&size=${limit}`;
return httpGetInterceptor(url);
}

View File

@ -91,6 +91,27 @@ export async function getIndeksData() {
); );
} }
export async function getIndeksDataFilter(
type: string,
search: string,
category: string,
size = 10,
page = 0,
sortBy = "createdAt",
format = "",
tag = "",
group = "",
startDate = "",
endDate = "",
month = "",
year = "",
isInt = false
) {
return await httpGetInterceptor(
`blog/public/pagination?enablePage=1&sort=desc&sortBy=${sortBy}&size=${size}&page=${page}&typeId=${type}&title=${search}&categoryId=${category}&fileFormats=${format}&tags=${tag}&group=${group}&startDate=${startDate}&endDate=${endDate}&month=${month}&year=${year}&isInt=${isInt}`
);
}
export async function getDetail(slug: string) { export async function getDetail(slug: string) {
return await httpGetInterceptor(`media/public?slug=${slug}&state=mabes`); return await httpGetInterceptor(`media/public?slug=${slug}&state=mabes`);
} }