diff --git a/src/components/Activity.js b/src/components/Activity.js index 86956db..0b44b3a 100644 --- a/src/components/Activity.js +++ b/src/components/Activity.js @@ -7,74 +7,79 @@ import { useEffect, useState } from "react"; import { client } from "@/config/appwrite-client"; export default function Activity() { - const [activity, setActivity] = useState([]); + const [activity, setActivity] = useState([]); - const getActivity = async () => { - const res = await fetch("/api/activity"); - const data = await res.json(); - setActivity(data); - }; + const getActivity = async () => { + const res = await fetch("/api/activity"); + const data = await res.json(); + setActivity(data); + }; - useEffect(() => { - const events = [ - `databases.${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID}.collections.${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID}.documents`, - ]; - client.subscribe(events, () => getActivity()); - getActivity(); - }, []); + useEffect(() => { + const events = [ + `databases.${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID}.collections.${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID}.documents`, + ]; + client.subscribe(events, () => getActivity()); + getActivity(); + }, []); - return ( - <> -
-

- Activity feed -

- {/* +
+

+ Activity feed +

+ {/*
View all */} -
- - - ); +
+ + + ); } diff --git a/src/components/ListSkeletons/RepoListSkeleton.js b/src/components/ListSkeletons/RepoListSkeleton.js new file mode 100644 index 0000000..738e98b --- /dev/null +++ b/src/components/ListSkeletons/RepoListSkeleton.js @@ -0,0 +1,12 @@ +const RepoListSkeleton = () => { + return ( +
+
+
+
+
+
+ ); +}; + +export default RepoListSkeleton; diff --git a/src/components/Repos.js b/src/components/Repos.js index c099540..5630474 100644 --- a/src/components/Repos.js +++ b/src/components/Repos.js @@ -1,138 +1,75 @@ "use client"; -import Image from "next/image"; -import Link from "next/link"; import { useEffect, useState } from "react"; -import { ChevronRightIcon } from "@heroicons/react/20/solid"; +import dynamic from "next/dynamic"; import { client } from "@/config/appwrite-client"; -import { classNames } from "@/utils/classNames"; +import RepoListSkeleton from "./ListSkeletons/RepoListSkeleton"; + +const RepoList = dynamic(() => import("./componentList/RepoList"), { + loading: RepoListSkeleton, + ssr: false, +}); -const statuses = { - research: "text-orange-500 bg-orange-100/10", - recommend: "text-green-400 bg-green-400/10", - caution: "text-rose-400 bg-rose-400/10", -}; -const badges = { - research: "text-orange-500 bg-orange-100/10 ring-orange-400/20", - recommend: "text-green-400 bg-green-400/10 ring-green-400/20", - caution: "text-rose-400 bg-rose-400/10 ring-rose-400/20", -}; const groups = { - recommend: 70, - research: 40, + recommend: 70, + research: 40, }; const calStatus = (percentage) => { - if (percentage >= groups.recommend) { - return "recommend"; - } - if (percentage >= groups.research && percentage < groups.recommend) { - return "research"; - } - return "caution"; + if (percentage >= groups.recommend) { + return "recommend"; + } + if (percentage >= groups.research && percentage < groups.recommend) { + return "research"; + } + return "caution"; }; export default function Repos({ minimumVotes = 5, keyword, sort }) { - const [repos, setRepos] = useState([]); - const getRepos = async () => { - const params = []; - if (minimumVotes) { - params.push(`minimumVotes=${minimumVotes}`); - } - if (keyword) { - params.push(`keyword=${keyword}`); - } - if (sort) { - params.push(`sort=${sort}`); - } - const res = await fetch( - `/api/repos${params.length ? `?${params.join("&")}` : ""}` - ); + const [repos, setRepos] = useState([]); + const getRepos = async () => { + const params = []; + if (minimumVotes) { + params.push(`minimumVotes=${minimumVotes}`); + } + if (keyword) { + params.push(`keyword=${keyword}`); + } + if (sort) { + params.push(`sort=${sort}`); + } + const res = await fetch( + `/api/repos${params.length ? `?${params.join("&")}` : ""}` + ); - const data = await res.json(); + const data = await res.json(); - const repos = data.map((repo) => { - const percentage = Math.round((repo.rating / 5) * 100); - return { - ...repo, - percentage, - status: calStatus(percentage), - }; - }); + const repos = data.map((repo) => { + const percentage = Math.round((repo.rating / 5) * 100); + return { + ...repo, + percentage, + status: calStatus(percentage), + }; + }); - setRepos(repos); - }; + setRepos(repos); + }; - useEffect(() => { - const events = [ - `databases.${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID}.collections.${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID}.documents`, - ]; - client.subscribe(events, () => getRepos()); - getRepos(); - }, [keyword, sort]); + useEffect(() => { + const events = [ + `databases.${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID}.collections.${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID}.documents`, + ]; + client.subscribe(events, () => getRepos()); + getRepos(); + }, [keyword, sort]); - return ( - - ); + return ( + + ); } diff --git a/src/components/SideNav.js b/src/components/SideNav.js index 1f161f0..8b2c7b3 100644 --- a/src/components/SideNav.js +++ b/src/components/SideNav.js @@ -51,7 +51,7 @@ export default function SideNav({ setKeyword, children }) { account.createOAuth2Session( "github", `${process.env.NEXT_PUBLIC_BASE_URL}/`, - `${process.env.NEXT_PUBLIC_BASE_URL}/` + `${process.env.NEXT_PUBLIC_BASE_URL}/`, ); }; diff --git a/src/components/Stats.js b/src/components/Stats.js index 00050ed..361febc 100644 --- a/src/components/Stats.js +++ b/src/components/Stats.js @@ -6,56 +6,56 @@ import { client } from "@/config/appwrite-client"; import { abbreviateNumber } from "@/utils/abbreviateNumbers"; export default function Stats() { - const [stats, setStats] = useState([]); + const [stats, setStats] = useState([]); - const getStats = async () => { - const res = await fetch("/api/stats"); - const data = await res.json(); - const stats = [ - { name: "Total Ratings", value: data.ratings, unit: "⭐️" }, - { name: "Total Repos", value: data.repos, unit: "GitHub" }, - { name: "Total Stars", value: data.stars, unit: "⭐️" }, - { - name: "Recommended Repos", - value: ((data.stars / data.ratings / 5) * 100).toFixed(1), - unit: "%", - }, - ]; - setStats(stats); - }; + const getStats = async () => { + const res = await fetch("/api/stats"); + const data = await res.json(); + const stats = [ + { name: "Total Ratings", value: data.ratings, unit: "⭐️" }, + { name: "Total Repos", value: data.repos, unit: "GitHub" }, + { name: "Total Stars", value: data.stars, unit: "⭐️" }, + { + name: "Recommended Repos", + value: ((data.stars / data.ratings / 5) * 100).toFixed(1), + unit: "%", + }, + ]; + setStats(stats); + }; - useEffect(() => { - const events = [ - `databases.${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID}.collections.${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID}.documents`, - ]; - client.subscribe(events, () => getStats()); - getStats(); - }, []); + useEffect(() => { + const events = [ + `databases.${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID}.collections.${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID}.documents`, + ]; + client.subscribe(events, () => getStats()); + getStats(); + }, []); - return ( -
-
-
- {stats.map((stat) => ( -
-

- {stat.name} -

-

- - {abbreviateNumber(stat.value)} - - {stat.unit ? ( - {stat.unit} - ) : null} -

-
- ))} -
-
-
- ); + return ( +
+
+
+ {stats.map((stat) => ( +
+

+ {stat.name} +

+

+ + {abbreviateNumber(stat.value)} + + {stat.unit ? ( + {stat.unit} + ) : null} +

+
+ ))} +
+
+
+ ); } diff --git a/src/components/Users.js b/src/components/Users.js index 3ebb89e..f4675d1 100644 --- a/src/components/Users.js +++ b/src/components/Users.js @@ -23,7 +23,7 @@ export default async function Users() { const ratings = await new Databases(clientAdmin()).listDocuments( process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID, process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID, - [Query.limit(1000)] + [Query.limit(1000)], ); const users = ratings.documents.reduce((acc, rating) => { if (!acc[rating.username]) { diff --git a/src/components/componentList/RepoList.js b/src/components/componentList/RepoList.js new file mode 100644 index 0000000..d38c9d8 --- /dev/null +++ b/src/components/componentList/RepoList.js @@ -0,0 +1,79 @@ +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { ChevronRightIcon } from "@heroicons/react/20/solid"; +import { classNames } from "@/utils/classNames"; + +const statuses = { + research: "text-orange-500 bg-orange-100/10", + recommend: "text-green-400 bg-green-400/10", + caution: "text-rose-400 bg-rose-400/10", +}; +const badges = { + research: "text-orange-500 bg-orange-100/10 ring-orange-400/20", + recommend: "text-green-400 bg-green-400/10 ring-green-400/20", + caution: "text-rose-400 bg-rose-400/10 ring-rose-400/20", +}; + +const RepoList = ({ repo }) => { + return ( + <> +
  • + {`Logo +
    +
    +
    +
    +
    +

    + + {repo.owner} + / + {repo.name} + + +

    +
    +
    +

    {repo.description}

    + + + +

    {repo.status}

    +
    +
    +
    + {repo.rating.toFixed(1)} / 5 ({repo.votes}) +
    +
  • + + ); +}; + +export default RepoList; diff --git a/tailwind.config.js b/tailwind.config.js index f195917..1bfc2d4 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,18 +1,18 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: [ - "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", - "./src/components/**/*.{js,ts,jsx,tsx,mdx}", - "./src/app/**/*.{js,ts,jsx,tsx,mdx}", - ], - theme: { - extend: { - backgroundImage: { - "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", - "gradient-conic": - "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", - }, - }, - }, - plugins: [require("daisyui"), require("@tailwindcss/forms")], + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + backgroundImage: { + "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", + "gradient-conic": + "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", + }, + }, + }, + plugins: [require("daisyui"), require("@tailwindcss/forms")], };