Skip to content

Commit

Permalink
🚧 wip(profile): add profileHelperService for util
Browse files Browse the repository at this point in the history
  • Loading branch information
lwinmoepaing committed Oct 21, 2023
1 parent db10ce2 commit f0bd638
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 71 deletions.
21 changes: 8 additions & 13 deletions src/app/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Container from '@/components/Common/Container/Container';
import APP_CONFIG from '@/config/config';
import { Metadata } from 'next';
import Container from "@/components/Common/Container/Container";
import APP_CONFIG from "@/config/config";
import { Metadata } from "next";

import ProfileCardList from '@/components/Profile/ProfileCardList/ProfileCardList';
import { allProfiles } from 'contentlayer/generated';
import SpacingDivider from '@/components/Common/SpacingDivider/SpacingDivider';
import ProfileCardList from "@/components/Profile/ProfileCardList/ProfileCardList";
import { allProfiles } from "contentlayer/generated";
import SpacingDivider from "@/components/Common/SpacingDivider/SpacingDivider";
import { profileHelperService } from "@/utils/profileHelper";

export const metadata: Metadata = {
title: `Profile List | ${APP_CONFIG.title}`,
Expand All @@ -16,13 +17,7 @@ const getAllProfileList = async () => {
};

const ProfileListPage = async () => {
const profiles = (await getAllProfileList()).map((profile) => {
// just clean some invisible space like \r \n \t in the data
return {
...profile,
tags: (profile.tags ?? []).map((tag) => tag.trim()),
};
});
const profiles = await getAllProfileList();

return (
<Container>
Expand Down
77 changes: 19 additions & 58 deletions src/components/Profile/ProfileCardList/ProfileCardList.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
'use client';
"use client";

import SpacingDivider from '@/components/Common/SpacingDivider/SpacingDivider';
import TitleText from '@/components/Common/TitleText/TitleText';
import SquareBox from '@/components/Ui/SquareBox/SquareBox';
import { cn, generateColor } from '@/utils';
import { Profile } from 'contentlayer/generated';
import Image from 'next/image';
import Link from 'next/link';
import { useSearchParams, useRouter } from 'next/navigation';
import { useMemo } from 'react';
import SpacingDivider from "@/components/Common/SpacingDivider/SpacingDivider";
import TitleText from "@/components/Common/TitleText/TitleText";
import SquareBox from "@/components/Ui/SquareBox/SquareBox";
import { cn, generateColor } from "@/utils";
import { profileHelperService } from "@/utils/profileHelper";
import { Profile } from "contentlayer/generated";
import Image from "next/image";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";

type TPropsProfileCardList = {
profiles: Profile[];
Expand All @@ -19,12 +19,12 @@ const Tag = ({ tag }: { tag: string }) => {
const router = useRouter();

const tmpSearchParam = new URLSearchParams(searchParams.toString());
tmpSearchParam.set('tag', tag);
tmpSearchParam.set("tag", tag);

return (
<TitleText
className={cn(
'inline-block cursor-pointer text-[10px] px-2 py-1 rounded-full mb-1 mr-[4px] bg-opacity-50 hover:bg-opacity-80',
"inline-block cursor-pointer text-[10px] px-2 py-1 rounded-full mb-1 mr-[4px] bg-opacity-50 hover:bg-opacity-80",
generateColor()
)}
key={tag}
Expand All @@ -41,51 +41,12 @@ const Tag = ({ tag }: { tag: string }) => {

const ProfileCardList = ({ profiles }: TPropsProfileCardList) => {
const searchParams = useSearchParams();
const tag = searchParams.get('tag') ?? '';
const searchTag = searchParams.get("tag") ?? "";

const uniqueTags = useMemo(() => {
const tags: string[] = [];
const tmpSet = new Set(profiles.map((profile) => profile.tags ?? []).flat());
tmpSet.forEach((tag) => void tags.push(tag));
return tags;
}, [profiles]);

const filteredProfiles = useMemo(() => {
if (tag.length === 0) return profiles;

const filtered = profiles.filter((profile) => {
let found = false;

profile.tags?.forEach((pTag) => {
const profileTag = pTag.toLowerCase();
const searchTag = tag.toLowerCase();

if (profileTag === searchTag) {
// exact match
found = true;
} else if (profileTag === searchTag + 'js' || profileTag === searchTag + '.js') {
// try add js or .js extension to search tag
found = true;
} else if (
profileTag === searchTag.replace(/\.js$/, '') ||
profileTag === searchTag.replace(/js$/, '')
) {
// try remove js or .js extension from search tag
found = true;
} else if (profileTag + 'js' === searchTag || profileTag + '.js' === searchTag) {
found = true;
} else if (
profileTag === searchTag.replace(/\.js$/, '') + 'js' ||
profileTag === searchTag.replace(/js$/, '') + '.js'
) {
// try swap .js and js extension
found = true;
}
});
return found;
});
return filtered;
}, [profiles, tag]);
const { uniqueTags, foundProfiles: filteredProfiles } = profileHelperService(
profiles,
searchTag
);

return (
<>
Expand All @@ -106,14 +67,14 @@ const ProfileCardList = ({ profiles }: TPropsProfileCardList) => {
<Link href={`/profile/${profile.slugAsParams}`}>
<SquareBox
className={cn(
'w-full h-full transition ease-out cursor-pointer hover:opacity-80 hover:-translate-y-1 bg-opacity-30 min-h-[130px]',
"w-full h-full transition ease-out cursor-pointer hover:opacity-80 hover:-translate-y-1 bg-opacity-30 min-h-[130px]",
bgColor
)}
>
<div className="flex flex-row items-center mb-2 space-x-2">
<div
className={cn(
'flex justify-center items-center h-10 w-10 rounded-full overflow-hidden relative',
"flex justify-center items-center h-10 w-10 rounded-full overflow-hidden relative",
bgColor
)}
>
Expand Down
76 changes: 76 additions & 0 deletions src/utils/profileHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Profile } from "contentlayer/generated";

export const getUniqueTags = (tags: string[]) => {
const uniqueTags: string[] = [];
new Set(tags).forEach((tag) => void uniqueTags.push(tag));
return uniqueTags;
};

export const profileHelperService = (
profiles: Profile[],
searchTag: string = ""
) => {
const tags: string[][] = [];
const foundProfiles: Profile[] = [];

// I Juz Wanna loop onetime of profile list
profiles.forEach((profile) => {
// Thanks to Bro Hein Thant for tag-search feature
// https://github.com/heinthanth

// just clean some invisible space like \r \n \t in the data
const profileTags = (profile.tags ?? []).map((tag) => tag.trim());
profile.tags = profileTags;
tags.push(profileTags);

if (!!searchTag) {
let isAlreayIncludedInProfile = false;
profileTags.forEach((pTag) => {
const profileTag = pTag.toLowerCase();
const sTagLowerCase = searchTag.toLowerCase();

if (isAlreayIncludedInProfile) return;

if (profileTag === sTagLowerCase) {
// exact match
foundProfiles.push(profile);
isAlreayIncludedInProfile = true;
} else if (
profileTag === sTagLowerCase + "js" ||
profileTag === sTagLowerCase + ".js"
) {
// try add js or .js extension to search tag
foundProfiles.push(profile);
isAlreayIncludedInProfile = true;
} else if (
profileTag === sTagLowerCase.replace(/\.js$/, "") ||
profileTag === sTagLowerCase.replace(/js$/, "")
) {
// try remove js or .js extension from search tag
foundProfiles.push(profile);
isAlreayIncludedInProfile = true;
} else if (
profileTag + "js" === sTagLowerCase ||
profileTag + ".js" === sTagLowerCase
) {
foundProfiles.push(profile);
isAlreayIncludedInProfile = true;
} else if (
profileTag === sTagLowerCase.replace(/\.js$/, "") + "js" ||
profileTag === sTagLowerCase.replace(/js$/, "") + ".js"
) {
// try swap .js and js extension
foundProfiles.push(profile);
isAlreayIncludedInProfile = true;
}
});
}
});

const uniqueTags = getUniqueTags(tags.flat(1));

return {
foundProfiles: !!searchTag ? foundProfiles : profiles,
uniqueTags,
};
};

0 comments on commit f0bd638

Please sign in to comment.