Skip to content
This repository has been archived by the owner on Jul 3, 2023. It is now read-only.

Commit

Permalink
Merge pull request #88 from Depok-Kita/staging
Browse files Browse the repository at this point in the history
Staging to Main
  • Loading branch information
edutjie authored Aug 31, 2022
2 parents 5d02cdb + 1b2b9be commit 6cc5b9f
Show file tree
Hide file tree
Showing 28 changed files with 4,241 additions and 5,466 deletions.
6 changes: 3 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ updates:
directory: "/" # Location of package manifests
schedule:
interval: "daily"
reviewers:
- "edutjie"
- "marcellinuselbert"
# reviewers:
# - "edutjie"
# - "marcellinuselbert"
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.tabSize": 2
"editor.tabSize": 2,
"git.mergeEditor": false
}
1 change: 1 addition & 0 deletions components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export * from "./hooks";
export * from "./toast";
export * from "./card";
export * from "./modules";
export * from "./modules";
export * from "./section";
328 changes: 328 additions & 0 deletions components/modules/artikel/ArtikelArtikelLainnya.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
import { Body, LoadingScreen, ShareLinkToClipboard } from "@components";
import Link from "next/link";
import Image from "next/image";
import axios from "axios";
import { useState, useEffect } from "react";
import { useWindowSize } from "@hooks";
import { Skeleton, SkeletonCircle, SkeletonText } from "@chakra-ui/react";
const removeMd = require("remove-markdown");

type ArtikelArtikelLainnyaProps = {
className?: string;
// Prioritas total > filter (topic) > search
total?: number; // Untuk mendapatkan artikel dengan jumlah tertentu
filter?: string; // Untuk mendapatkan artikel berdasarkan topik
search?: string; // Untuk mendapatkan artikel berdasarkan search
mode?: string; // Untuk menyetel mode splitting by 2 atau engga
bodyPage?: boolean; // Untuk mendapatkan posisi peletakan artikel lainnya ada di mana (bodyPage vs mainPage)
children?: React.ReactNode;
page?: string;
};

export const ArtikelArtikelLainnya = ({
children,
className,
total,
filter,
search,
mode,
bodyPage,
page,
}: ArtikelArtikelLainnyaProps) => {
const { width } = useWindowSize();
// GET : api/articles
// FETCH DI SINI KARENA KOMPONEN DIGUNAKAN BEBERAPA BAGIAN
const [articles, setArticles] = useState([]);
const [articlesLoading, setArticlesLoading] = useState(true);

// Handle panjang judul
let slicingTitleLength = 40; // Default
let limitTitleCharLength = 40; // Default
// Pengecualian saat ada di bodyPage dan desktop
if (width >= 1280 && bodyPage) {
slicingTitleLength = 30;
limitTitleCharLength = 30;
}

useEffect(() => {
axios.get("/api/articles").then((response) => {
setArticles(response.data);
setArticlesLoading(false);
});
}, []);

// Menampilkan artikel lain berdasarkan total dan filter topik
let artikelDitampilkan = articles;

// FILTER PRIORITAS 1
// --------------------------- FILTER TOTAL ---------------------------
// Undefined hanya ketika total tidak diinisiasikan nilainua => default (tidak dilakukan slicing)
if (total != undefined) {
artikelDitampilkan = artikelDitampilkan.slice(0, total);
}

// FILTER PRIORITAS 2
// --------------------------- FILTER TOPIC ---------------------------
// Ketika nilai filter tidak default (All) maka lakukan pemfilteran
const filteringTopic = (article: any, filter: any) => {
for (let topic of article.topics) {
if (topic.name == filter) {
return true;
}
}
// Ketika tidak ditemukan topik dengan nama sesuai filter
return false;
};
if (filter != "All") {
artikelDitampilkan = artikelDitampilkan.filter((article: any) =>
filteringTopic(article, filter)
);
}

// FILTER PRIORITAS 3
// --------------------------- FILTER SEARCH ---------------------------
// Ketika nilai search tidak default ("") maka lakukan pemfilteran
const filteringSearchInput = (article: any, search: any) => {
// Ketika dalam judul artikel terdapat search value
if (article.title.toLowerCase().includes(search.toLowerCase())) {
return true;
}
// Saat search value tidak ada di dalam judul artikel
return false;
};
if (search != "") {
artikelDitampilkan = artikelDitampilkan.filter((article: any) =>
filteringSearchInput(article, search)
);
}

// Melakukan format tanggal
const dateFormat = (date: any) => {
return date.slice(8) + "/" + date.slice(5, 7) + "/" + date.slice(0, 4);
};

// https://npm.io/package/remove-markdown
// https://www.npmjs.com/package/remove-markdown
const articlesClear = artikelDitampilkan.map((article: any) => {
return {
...article,
title: removeMd(article.title),
body: removeMd(article.body),
};
});

// Membersihkan teks dari format dan nama suatu format seperti .jpg dst
const removedFileFormat = [".jpg", ".png", ".jpeg"];
const removeFormatFile = (body: string) => {
// Menyusun body baru
let bodyBaru = "";
for (let kata of body.split(" ")) {
let adaFormat = false;
for (let formt of removedFileFormat) {
if (kata.includes(formt)) {
adaFormat = true;
break;
}
}
// Kalau ditemukan format dalam kata tersebut maka dicontinue
if (adaFormat) {
continue;
} else {
// Kalau gaada ditambahkan ke bodyBaru
bodyBaru += kata + " ";
}
}
return bodyBaru;
};

const articlesFormatClear = articlesClear.map((article: any) => {
return {
...article,
body: removeFormatFile(article.body),
};
});

if (mode == "normal") {
return (
<div className="flex flex-col">
{articlesFormatClear.map((article: any) => (
<Skeleton
isLoaded={!articlesLoading}
className={`${page === article.slug ? "hidden" : ""}`}
rounded="lg"
mb={2}
key={article.id}
>
<div className="flex justify-center">
<div
className={
bodyPage
? "mobile:w-[315px] tablet:w-[600px] desktop:w-[380px] tablet:pb-3"
: "mobile:w-[315px] tablet:w-[600px] desktop:w-[700px] tablet:pb-3"
}
>
<div
className={
bodyPage
? "flex justify-between border-b border-powder pb-1 pt-2 relative tablet:pb-10 desktop:pb-2"
: "flex justify-between border-b border-powder pb-1 pt-2 relative tablet:pb-10 desktop:pb-12 desktop:pt-5"
}
>
<Link href={"/artikel/" + article?.slug}>
<div className="mobile:max-w-[180px] tablet:max-w-[400px] desktop:max-w-[460px] hover:cursor-pointer">
<Body
preset="p3"
className={
bodyPage
? "mobile:text-[8px] tablet:text-[12px] desktop:text-[10px]"
: "mobile:text-[8px] tablet:text-[12px] desktop:text-[15px]"
}
>
{dateFormat(article?.published)}
</Body>
<Body
preset={
width >= 1280 ? "b1" : width >= 768 ? "b2" : "b3"
}
className={
bodyPage
? "mobile:text-[11px] tablet:text-[18px] desktop:text-[16px]"
: "mobile:text-[11px] tablet:text-[18px] desktop:text-[23px]"
}
>
{/* Handle title yang terlalu panjang */}
{article?.title.length >= limitTitleCharLength
? article?.title.slice(0, slicingTitleLength) + " ..."
: article?.title}
</Body>
{width >= 768 && !bodyPage && (
<Body
preset="p3"
className={width >= 1280 ? "text-[15px]" : ""}
>
{article?.body.slice(0, 240) + " ..."}
</Body>
)}
<div className="flex flex-wrap gap-1 absolute mobile:bottom-2 tablet:bottom-3">
{article?.topics.map((topic: any) => (
<div
className={
bodyPage
? "bg-totalwhite border-totalwhite shadow-inner rounded-2xl text-cerulean text-[8px] font-bold px-[6px] py-[1px] tablet:text-[10px] desktop:text-[10px] desktop:px-[6px] desktop:py-[1px]"
: "bg-totalwhite border-totalwhite shadow-inner rounded-2xl text-cerulean text-[8px] font-bold px-[6px] py-[1px] tablet:text-[10px] desktop:text-[13px] desktop:px-[8px] desktop:py-[2px]"
}
key={topic.id}
>
{topic.name}
</div>
))}
</div>
</div>
</Link>
<ShareLinkToClipboard
className={
width >= 768
? bodyPage
? "absolute bottom-3 right-28 w-[18px]"
: "absolute bottom-3 right-0 w-6"
: "right-24"
}
link={article.slug}
/>
<Link href={"/artikel/" + article?.slug}>
<div className={width >= 1280 && !bodyPage ? "pt-6" : ""}>
<Image
src={article?.photoUrl}
alt={article?.photoAlt}
width={
width >= 1280
? bodyPage
? 100
: 200
: width >= 768
? 165
: 85
}
height={
width >= 1280
? bodyPage
? 75
: 130
: width >= 768
? 100
: 60
}
className="rounded-md tablet:rounded-xl "
objectFit="cover"
/>
</div>
</Link>
</div>
</div>
</div>
</Skeleton>
))}
</div>
);
} else {
// Saat mode split
return (
<div className="grid grid-cols-2 gap-x-6">
{articlesFormatClear.map((article: any) => (
<Skeleton
isLoaded={!articlesLoading}
className={`${page === article.slug ? "hidden" : ""}`}
rounded="lg"
key={article.id}
>
<div className="flex justify-center" key={article.id}>
<div className="w-[600px] pb-3">
<div className="flex justify-between border-b border-powder pb-1 pt-2 relative">
<Link href={"/artikel/" + article?.slug}>
<div className="mobile:max-w-[180px] tablet:max-w-[400px] desktop:max-w-[460px] hover:cursor-pointer">
<Body preset="p3" className="text-[8.5px]">
{dateFormat(article?.published)}
</Body>
<Body preset="b3" className="text-[13px]">
{/* Handle title yang terlalu panjang */}
{article?.title.length >= 40
? article?.title.slice(0, 30) + " ..."
: article?.title}
</Body>
<div className="flex flex-wrap gap-1 absolute bottom-2">
{article?.topics.map((topic: any) => (
<div
className="bg-totalwhite border-totalwhite shadow-inner rounded-2xl text-cerulean font-bold px-[6px] py-[1px] text-[7px]"
key={topic.id}
>
{topic.name}
</div>
))}
</div>
</div>
</Link>
<ShareLinkToClipboard
className="absolute bottom-[10px] right-[95px] w-4"
link={article.slug}
/>
<Link href={"/artikel/" + article?.slug}>
<div>
<Image
src={article?.photoUrl}
alt={article?.photoAlt}
width={85}
height={60}
className="rounded-md"
objectFit="cover"
/>
</div>
</Link>
</div>
</div>
</div>
</Skeleton>
))}
</div>
);
}
};
Loading

0 comments on commit 6cc5b9f

Please sign in to comment.