feat: add components

This commit is contained in:
rizaldy 2024-01-31 00:49:51 +07:00
parent c7f97a3dc2
commit 627733ceb9
6 changed files with 232 additions and 0 deletions

32
components/Feed.js Normal file
View File

@ -0,0 +1,32 @@
const Feed = ({
media,
type,
setOverlayContent,
currentIndex,
limitPerPage,
}) => (
<main className="grid grid-cols-3 gap-1">
{media
.slice(currentIndex, limitPerPage)
.map(({ id, url, previewPath, embedPath = url }) => (
<a
key={id}
href={url}
target="_blank"
rel="noopener noreferer"
onClick={(e) => {
e.preventDefault();
setOverlayContent({
url: embedPath,
type,
});
}}
>
<img alt={url} src={previewPath} className={`aspect-${type}`} />
</a>
))}
</main>
);
export default Feed;

49
components/Footer.js Normal file
View File

@ -0,0 +1,49 @@
import Link from "next/link";
import { YEAR_TO_BUMP } from "../constants";
const Footer = ({ license, links, repo, commitID }) => (
<footer className="flex items-center justify-between flex-wrap py-4 text-center mt-10">
<div className="w-10/12 md:w-7/12 mx-auto font-semibold">
<div className="text-sm mb-10">
{links.map(({ url, label }) => (
<Link key={url + label} href={url} className="mx-4">
{label}
</Link>
))}
<Link href={repo} className="mx-4">
Source Code
</Link>
</div>
<div className="text-sm font-normal text-neutral-400">
<p>
&copy; {YEAR_TO_BUMP}{" "}
<Link
className="text-neutral-600"
target="_blank"
rel="noopener noreferer"
href="https://github.com/faultables"
>
faultables
</Link>{" "}
All media is licensed under{" "}
<Link className="underline" href={license.url}>
{license.name}
</Link>{" "}
unless stated otherwise {" "}
<Link
className="text-neutral-600"
target="_blank"
rel="noopener noreferer"
href={`${repo}/commit/${commitID}`}
>
{commitID}
</Link>
</p>
</div>
</div>
</footer>
);
export default Footer;

21
components/Navbar.js Normal file
View File

@ -0,0 +1,21 @@
import Link from "next/link";
const Navbar = ({ name, logo }) => (
<nav className="flex py-2 border-b">
<div className="w-3/12 md:w-7/12 md:mx-auto">
<div className="md:w-2/12">
<Link href="/">
{logo ? (
<img alt={name} src={logo} className="w-full" />
) : (
<h1 className="font-bold leading-relaxed tracking-tight text-2xl text-neutral-800">
{name}
</h1>
)}
</Link>
</div>
</div>
</nav>
);
export default Navbar;

57
components/Overlay.js Normal file
View File

@ -0,0 +1,57 @@
import { MEDIA_TYPE } from "../constants";
const OverlayContent = ({ overlayContent }) => {
if (overlayContent?.type === MEDIA_TYPE.PHOTOS) {
return (
<img
alt={overlayContent?.url}
src={overlayContent?.url}
className="z-20 cursor-default"
/>
);
} else if (overlayContent?.type === MEDIA_TYPE.VIDEOS) {
return (
<iframe
width="50%"
height="50%"
allow="fullscreen"
sandbox="allow-same-origin allow-scripts allow-popups"
src={overlayContent?.url}
></iframe>
);
}
};
const Overlay = ({ overlayContent, closeOverlay }) => {
const isOverlayOpen = overlayContent?.type !== undefined;
return (
<div
onClick={closeOverlay}
className={`${
isOverlayOpen
? "bg-neutral-800/95 fixed w-screen h-screen left-0 top-0 cursor-pointer"
: ""
}`}
>
{isOverlayOpen ? (
<p
onClick={closeOverlay}
className="fixed right-0 bottom-0 m-5 text-white rounded text-sm"
>
Click anywhere or press "Escape" to close
</p>
) : null}
<div
className={`flex justify-center items-center ${
isOverlayOpen ? "h-screen w-screen" : "h-0 w-0"
}`}
>
<OverlayContent overlayContent={overlayContent} />
</div>
</div>
);
};
export default Overlay;

46
components/Profile.js Normal file
View File

@ -0,0 +1,46 @@
const Profile = ({ profile, totalPosts }) => (
<div className="flex flex-warp">
<div className="lg:w-4/12 w-3/12 md:py-10 lg:px-20 md:px-10">
<img
alt={profile.display_name}
src={profile.avatar}
className="w-100 rounded-full mx-auto border border-gray-200 p-1"
/>
</div>
<div className="lg:w-9/12 md:w-10/12 px-10 mb-5 md:p-5">
<div className="flex items-center">
<h2 className="text-2xl font-semibold">{profile.username}</h2>
<div className="ml-4">
<a
className="rounded-md bg-gray-100 px-5 font-semibold py-2 ml-2 text-sm leading-relaxed"
href={profile.follow_url}
>
Follow
</a>
<a
className="rounded-md bg-gray-100 px-5 font-semibold py-2 ml-2 text-sm leading-relaxed"
href={profile.message_url}
>
Message
</a>
</div>
</div>
<div className="my-5 font-bold text-sm">
<p>{totalPosts} posts</p>
</div>
<p className="font-bold mb-1">{profile.display_name}</p>
<p>{profile.about}</p>
<p className="leading-loose font-semibold text-blue-900">
<a
target="_blank"
rel="noopener noreferer"
href={`https://${profile.link}`}
>
{profile.link}
</a>
</p>
</div>
</div>
);
export default Profile;

27
components/Tab.js Normal file
View File

@ -0,0 +1,27 @@
const isActiveTab = (currentTab, activeTab) =>
currentTab === activeTab ? "border-t" : "";
const Tab = ({ activeTab, setActiveTab }) => (
<div className="flex items-center justify-center text-center gap-5 border-t mb-4">
<button
onClick={() => setActiveTab("photos")}
className={`uppercase tracking-tight font-semibold text-sm border-black pt-3 px-3 ${isActiveTab(
"photos",
activeTab
)}`}
>
Photos
</button>
<button
onClick={() => setActiveTab("videos")}
className={`uppercase tracking-tight font-semibold text-sm pt-3 px-3 border-black ${isActiveTab(
"videos",
activeTab
)}`}
>
Videos
</button>
</div>
);
export default Tab;