Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app/(about)/about/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ export const metadata = {
description: `Here are some details about my self.`,
};

/**
* Renders the About component.
* This component includes an overview cover section, skills section, and a contact message for potential projects.
*
* @returns {JSX.Element} - The rendered JSX element.
*/
export default function About() {
return (
<>
Expand Down
5 changes: 5 additions & 0 deletions src/app/(about)/contact/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export const metadata = {
};


/**
* Returns the Contact component that renders a section for contacting information.
*
* @returns {JSX.Element} - A React JSX element representing the contact section.
*/
export default function Contact() {
return (
<section className="w-full h-auto md:h-[75vh] border-b-2 border-solid border-dark dark:border-light flex flex-col md:flex-row items-center justify-center text-dark dark:text-light">
Expand Down
34 changes: 34 additions & 0 deletions src/app/blogs/[slug]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,37 @@ import { allBlogs } from "contentlayer/generated";
import { slug } from "github-slugger";
import Image from "next/image";

/**
* Generates static parameters for blog slugs.
*
* @async
* @returns {Promise<Array<{ slug: string }>>} - A promise that resolves to an array of objects, each containing a 'slug' property corresponding to a blog's flattened path.
* @throws {Error} - If there is an error during the generation process.
*
* Example usage:
* generateStaticParams().then((params) => {
* console.log(params);
* }).catch((error) => {
* console.error(error);
* });
*/
export async function generateStaticParams() {
return allBlogs.map((blog) => ({ slug: blog._raw.flattenedPath }));
}

/**
* Generates metadata for a blog post based on the provided parameters.
*
* @param {Object} params - The parameters required to fetch blog metadata.
* @param {string} params.slug - The slug of the blog post to retrieve.
* @returns {Promise<Object|undefined>} - A promise that resolves to an object containing blog metadata or undefined if no blog is found.
*
* @example
* const params = { slug: 'sample-blog-post' };
* generateMetadata(params).then(metadata => {
* console.log(metadata);
* });
*/
export async function generateMetadata({ params }) {
const blog = allBlogs.find((blog) => blog._raw.flattenedPath === params.slug);
if (!blog) {
Expand Down Expand Up @@ -56,6 +83,13 @@ export async function generateMetadata({ params }) {
};
}

/**
* The BlogPage component renders a blog post page based on the provided slug parameter.
* It fetches the blog post data, generates JSON-LD for SEO purposes, and displays the blog content.
*
* @param {Object} params - The parameters object containing the slug of the blog post.
* @returns {JSX.Element} - The JSX representing the blog page.
*/
export default function BlogPage({ params }) {
const blog = allBlogs.find((blog) => blog._raw.flattenedPath === params.slug);

Expand Down
33 changes: 33 additions & 0 deletions src/app/categories/[slug]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ import GithubSlugger, { slug } from "github-slugger";

const slugger = new GithubSlugger();

/**
* Generates static parameters for blog paths based on published blogs and their tags.
*
* This function iterates through all published blogs, extracts their tags,
* slugifies the tags to create unique slugs, and generates an array of paths
* including 'all' and each unique tag slug. Only includes tags from published blogs.
*
* @returns {Array<{slug: string}>} - An array of objects containing a slug for each unique tag.
* @throws {Error} If the `allBlogs` variable is not defined or is empty.
*/
export async function generateStaticParams() {
const categories = [];
const paths = [{ slug: "all" }];
Expand All @@ -24,6 +34,22 @@ export async function generateStaticParams() {
return paths;
}

/**
* Generates metadata based on the provided parameters.
*
* @async
* @function generateMetadata
* @param {Object} params - The parameters object containing necessary information.
* @param {string} params.slug - The slug used to determine the title and description of the blogs.
* @returns {Promise<Object>} A promise that resolves with an object containing the generated metadata.
* @throws Will throw an error if the params object is missing or if the slug parameter is invalid.
*
* @example
* // Example usage:
* generateMetadata({ slug: "all" })
* .then(metadata => console.log(metadata))
* .catch(error => console.error(error));
*/
export async function generateMetadata({ params }) {
return {
title: `${params.slug.replaceAll("-"," ")} Blogs`,
Expand All @@ -32,6 +58,13 @@ export async function generateMetadata({ params }) {
}


/**
* A React component that renders a category page based on the provided parameters.
*
* @param {Object} params - An object containing route parameters.
* @param {string} params.slug - The current category slug to filter blogs.
* @returns {JSX.Element} - The rendered CategoryPage component.
*/
const CategoryPage = ({ params }) => {
const allCategories = ["all"];
const blogs = allBlogs.filter((blog) => {
Expand Down
20 changes: 20 additions & 0 deletions src/app/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,26 @@ export const metadata = {
},
};

/**
* A React component that serves as the root layout for the application.
*
* @param {Object} props - The properties passed to this component.
* @param {React.ReactNode} props.children - Content to be rendered within the layout.
* @returns {React.ReactNode} - The rendered React element representing the root layout.
*
* This component renders a basic HTML structure with a header, footer,
* and a body that includes conditional rendering of a dark mode theme
* based on user preference or system settings. It also includes a script tag for
* handling theme switching and a class name for font styling using the `cx` utility.
*
* Example usage:
*
* ```jsx
* <RootLayout>
* <Home />
* </RootLayout>
* ```
*/
export default function RootLayout({ children }) {
return (
<html lang="en">
Expand Down
14 changes: 14 additions & 0 deletions src/app/manifest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/**
* Generates the manifest configuration for a Next.js application.
*
* @returns {Object} - The manifest configuration object.
* @property {string} name - The name of the application.
* @property {string} short_name - A shorter version of the application name, used in places where space is limited.
* @property {string} description - A brief description of the application.
* @property {string} start_url - The URL that the browser loads when opening the application.
* @property {string} display - Defines how the web app should be displayed to users. Possible values are 'fullscreen', 'standalone', 'minimal-ui', and 'browser'.
* @property {Array<Object>} icons - An array of icon objects, each representing an image that can be used by browsers on homescreens.
* @property {string} src - The URL of the icon file.
* @property {string} sizes - A string indicating the size of the icon in pixels.
* @property {string} type - The MIME type of the icon file, typically 'image/png'.
*/
export default function manifest() {
return {
name: 'Next.js App',
Expand Down
6 changes: 6 additions & 0 deletions src/app/not-found.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import Link from "next/link";

/**
* Represents a React functional component that renders a 404 error page.
*
* @function
* @returns {JSX.Element} - A JSX element representing the 404 error page.
*/
export default function NotFound() {
return (
<main className="my-32 w-full dark:bg-dark flex justify-center font-mr">
Expand Down
4 changes: 4 additions & 0 deletions src/components/About/AboutCoverSection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import Image from 'next/image'
import React from 'react'
import profileCharacter from "../../../public/character.png"

/**
* React functional component that renders an about cover section with an image and text content.
* @returns {JSX.Element} - The rendered JSX element of the about cover section.
*/
const AboutCoverSection = () => {
return (
<section className='w-full md:h-[75vh] border-b-2 border-solid border-dark dark:border-light flex flex-col md:flex-row items-center justify-center text-dark dark:text-light'>
Expand Down
7 changes: 7 additions & 0 deletions src/components/About/InsightRoll.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import React from "react";

/**
* A React component that renders a div with a list of insights, styled to roll across the screen.
*
* @param {Object} props - The properties for this component.
* @param {Array<String>} props.insights - An array of strings representing the insights to display.
* @returns {JSX.Element} A React element representing the InsightRoll component.
*/
const InsightRoll = ({ insights }) => {
return (
<div className="w-full bg-accent dark:bg-accentDark text-light dark:text-dark whitespace-nowrap overflow-hidden">
Expand Down
5 changes: 5 additions & 0 deletions src/components/About/Skills.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ const SkillList = [
"sanity",
];

/**
* Represents a component that displays the list of skills a person is comfortable with.
*
* @returns {JSX.Element} The JSX element representing the skills section.
*/
const Skills = () => {
return (
<section className="w-full flex flex-col p-5 xs:p-10 sm:p-12 md:p-16 lg:p-20 border-b-2 border-solid border-dark dark:border-light
Expand Down
7 changes: 7 additions & 0 deletions src/components/Blog/BlogLayoutOne.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import Link from "next/link";
import Image from "next/image";
import { slug } from "github-slugger";

/**
* A React component that displays blog layout with an image and title.
*
* @param {Object} props - The component's properties.
* @param {Object} props.blog - The blog data object containing details such as image, title, and tags.
* @returns {JSX.Element} - The rendered blog layout component.
*/
const BlogLayoutOne = ({ blog }) => {
return (
<div className="group inline-block overflow-hidden rounded-xl">
Expand Down
17 changes: 17 additions & 0 deletions src/components/Blog/BlogLayoutThree.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@ import Image from "next/image";
import Link from "next/link";
import React from "react";

/**
* React component for rendering a blog post layout.
*
* @param {Object} props - The properties object.
* @param {Object} props.blog - The blog post data.
* @param {string} props.blog.url - The URL of the blog post.
* @param {Object} props.blog.image - The image data for the blog post.
* @param {string} props.blog.image.filePath - The file path of the blog post image.
* @param {string} props.blog.image.blurhashDataUrl - The blurhash data URL for lazy loading.
* @param {number} props.blog.image.width - The width of the blog post image.
* @param {number} props.blog.image.height - The height of the blog post image.
* @param {Array<Object>} props.blog.tags - The tags associated with the blog post.
* @param {string} props.blog.title - The title of the blog post.
* @param {string} props.blog.publishedAt - The publication date of the blog post in ISO format.
*
* @returns {JSX.Element} - The rendered BlogLayoutThree component.
*/
const BlogLayoutThree = ({ blog }) => {
return (
<div className="group flex flex-col items-center text-dark dark:text-light">
Expand Down
14 changes: 14 additions & 0 deletions src/components/Blog/BlogLayoutTwo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ import Image from "next/image";
import Link from "next/link";
import React from "react";

/**
* Renders a blog layout with an image and text content.
*
* @param {Object} props - The component's properties.
* @param {Object} props.blog - The blog object containing details to display.
* @param {string} props.blog.url - The URL of the blog post.
* @param {string} props.blog.image.filePath - The file path of the blog image.
* @param {string} props.blog.image.blurhashDataUrl - The blur hash data URL for the blog image.
* @param {string} props.blog.title - The title of the blog post.
* @param {Array} props.blog.tags - An array of tags associated with the blog post.
* @param {Date} props.blog.publishedAt - The date the blog post was published.
*
* @returns {JSX.Element} - The rendered blog layout component.
*/
const BlogLayoutTwo = ({ blog }) => {
return (
<div className="group grid grid-cols-12 gap-4 items-center text-dark dark:text-light">
Expand Down
11 changes: 11 additions & 0 deletions src/components/Blog/Categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ import { slug } from "github-slugger";
import React from "react";
import Category from "./Category";

/**
* A React component that renders a list of categories with links.
*
* @param {Object} props - The props object for the Categories component.
* @param {Array<string>} props.categories - An array of category slugs.
* @param {string} props.currentSlug - The current category slug.
* @returns {JSX.Element} A React element representing the list of categories.
*
* @example
* <Categories categories={['technology', 'science', 'health']} currentSlug='technology' />
*/
const Categories = ({ categories, currentSlug }) => {
return (
<div className=" px-0 md:px-10 sxl:px-20 mt-10 border-t-2 text-dark dark:text-light border-b-2 border-solid border-dark dark:border-light py-4 flex items-start flex-wrap font-medium mx-5 md:mx-10">
Expand Down
11 changes: 11 additions & 0 deletions src/components/Blog/Category.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ import { cx } from "@/src/utils";
import Link from "next/link";
import React from "react";

/**
* A functional component that renders a category link with optional styling and active state handling.
*
* @param {Object} props - The properties passed to the component.
* @param {string} [props.link="#"] - The URL to navigate to when the link is clicked. Defaults to "#".
* @param {string} props.name - The name of the category displayed on the link.
* @param {boolean} [props.active=false] - Determines if the category is currently active, affecting its style. Defaults to false.
* @param {...Object} props - Additional properties that can be passed to the underlying Link component.
*
* @returns {JSX.Element} A JSX element representing a styled link for a category.
*/
const Category = ({ link = "#", name, active, ...props }) => {
return (
<Link
Expand Down
12 changes: 12 additions & 0 deletions src/components/Blog/RenderMdx.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ const mdxComponents = {
Image
}

/**
* React component to render MDX content from a blog post.
*
* @param {Object} props - The component props.
* @param {Object} props.blog - The blog post object containing the MDX content.
* @param {string} props.blog.body.code - The actual MDX code to be rendered.
* @returns {JSX.Element} - A React JSX element representing the rendered MDX content.
*
* @example
* // Example usage of RenderMdx component
* <RenderMdx blog={blogPost} />
*/
const RenderMdx = ({blog}) => {

const MDXContent = useMDXComponent(blog.body.code)
Expand Down
38 changes: 38 additions & 0 deletions src/components/Blog/ViewCounter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,36 @@ import React, { useEffect, useState } from "react";

const supabase = createClientComponentClient();

/**
* A React component that renders the number of views for a specific slug.
*
* @param {Object} props - The properties passed to the component.
* @param {string} props.slug - The unique identifier for the content being viewed.
* @param {boolean} [props.noCount=false] - Optional flag to disable view counting. Defaults to `false`.
* @param {boolean} [props.showCount=true] - Optional flag to control whether to display the count of views. Defaults to `true`.
* @returns {JSX.Element} - The rendered component.
*/
const ViewCounter = ({ slug, noCount = false, showCount = true }) => {
const [views, setViews] = useState(0);

useEffect(() => {
/**
* Asynchronously increments the view count for a given slug using Supabase RPC.
*
* @async
* @function
* @param {string} slug - The slug for which to increment the view count.
* @returns {Promise<void>} A promise that resolves when the view count has been incremented, or rejects if an error occurs.
*
* @example
* try {
* await incrementView("example-slug");
* } catch (error) {
* console.error("Failed to increment view count:", error);
* }
*
* @throws {Error} If there is an error during the RPC call or in the catch block.
*/
const incrementView = async () => {
try {
let { error } = await supabase.rpc("increment", {
Expand All @@ -32,6 +58,18 @@ const ViewCounter = ({ slug, noCount = false, showCount = true }) => {
}, [slug, noCount]);

useEffect(() => {
/**
* Increments the view count for a given slug.
*
* @async
* @function getViews
* @param {string} slug - The unique identifier of the resource whose views need to be incremented.
* @returns {undefined}
* @throws {Error} Throws an error if there is an issue fetching or updating the view count.
*
* Example usage:
* getViews("example-slug");
*/
const getViews = async () => {
try {
let { data, error } = await supabase
Expand Down
Loading