enzostvs HF staff commited on
Commit
92c8d86
1 Parent(s): b10df03
.vscode/settings.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "typescript.tsdk": "node_modules/typescript/lib"
3
+ }
app/page.tsx CHANGED
@@ -1,7 +1,6 @@
1
- import { Space } from "@/components/space";
2
- import { SpaceIcon } from "@/components/space_icon";
3
  import { fetchAllPages } from "@/utils";
4
  import { SpaceProps } from "@/utils/type";
 
5
 
6
  async function getSpaces() {
7
  try {
@@ -14,27 +13,10 @@ async function getSpaces() {
14
 
15
  export default async function Home() {
16
  const spaces = await getSpaces();
17
- console.log(spaces);
18
  return (
19
  <section className="flex h-screen overflow-auto">
20
- <div className="w-full container px-6 py-10 lg:py-20 mx-auto space-y-14">
21
- <header className="max-w-4xl mx-auto w-full text-center">
22
- <div className="mb-6 mx-auto font-regular text-xs text-center max-w-max rounded-full border-gray-200 bg-gray-50 border text-gray-700 px-3 py-2 transition-all duration-300">
23
- <SpaceIcon className="inline-block w-4 h-4 mr-2 drop-shadow-lg" />
24
- Browse {spaces.length} spaces
25
- </div>
26
- <h1 className="font-extrabold text-3xl text-black">
27
- Zero GPU Spaces
28
- </h1>
29
- <p className="text-neutral-500 font-regular text-base">
30
- Discover spaces with zero GPU usage on 🤗 Hugging Face Spaces.
31
- </p>
32
- </header>
33
- <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
34
- {spaces?.map((space: SpaceProps) => (
35
- <Space key={space.id} space={space} />
36
- ))}
37
- </div>
38
  </div>
39
  </section>
40
  );
 
 
 
1
  import { fetchAllPages } from "@/utils";
2
  import { SpaceProps } from "@/utils/type";
3
+ import { Spaces } from "@/components/spaces";
4
 
5
  async function getSpaces() {
6
  try {
 
13
 
14
  export default async function Home() {
15
  const spaces = await getSpaces();
 
16
  return (
17
  <section className="flex h-screen overflow-auto">
18
+ <div className="w-full container px-6 py-10 lg:py-20 mx-auto space-y-10 lg:space-y-14">
19
+ <Spaces spaces={spaces} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  </div>
21
  </section>
22
  );
components/sort.tsx ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import classNames from "classnames";
2
+ import { TiHeartFullOutline } from "react-icons/ti";
3
+ import { MdCalendarToday } from "react-icons/md";
4
+
5
+ interface Props {
6
+ value: "likes" | "createdAt";
7
+ onChange: (s: "createdAt" | "likes") => void;
8
+ }
9
+ export const Sort = ({ value, onChange }: Props) => {
10
+ return (
11
+ <div className="flex items-center justify-center border-[3px] rounded-full border-gray-50 drop-shadow-sm bg-gray-100 ring-[1px] ring-gray-200 gap-1">
12
+ <button
13
+ className={classNames(
14
+ "rounded-full pl-3 pr-4 py-2.5 transition-all duration-200 font-semibold text-xs hover:bg-gray-200/70 flex items-center justify-center gap-2",
15
+ {
16
+ "bg-black hover:!bg-black text-white": value === "likes",
17
+ }
18
+ )}
19
+ onClick={() => onChange("likes")}
20
+ >
21
+ <TiHeartFullOutline className="w-3.5 h-3.5" />
22
+ Likes
23
+ </button>
24
+ <button
25
+ className={classNames(
26
+ "rounded-full pl-3 pr-4 py-2.5 transition-all duration-200 font-semibold text-xs hover:bg-gray-200/70 flex items-center justify-center gap-2",
27
+ {
28
+ "bg-black hover:!bg-black text-white": value === "createdAt",
29
+ }
30
+ )}
31
+ onClick={() => onChange("createdAt")}
32
+ >
33
+ <MdCalendarToday className="w-3.5 h-3.5" />
34
+ Date
35
+ </button>
36
+ </div>
37
+ );
38
+ };
components/spaces/index.tsx ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client";
2
+ import { useMemo, useState } from "react";
3
+
4
+ import { SpaceProps } from "@/utils/type";
5
+ import { SpaceIcon } from "@/components/space_icon";
6
+ import { sortByCreatedAt, sortByLikes } from "@/utils";
7
+
8
+ import { Space } from "@/components/spaces/space";
9
+ import { Sort } from "@/components/sort";
10
+
11
+ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({
12
+ spaces: initialSpaces,
13
+ }) => {
14
+ const [sort, setSort] = useState<"likes" | "createdAt">("createdAt");
15
+
16
+ const spaces = useMemo(() => {
17
+ if (sort === "likes") {
18
+ return sortByLikes(initialSpaces);
19
+ }
20
+ return sortByCreatedAt(initialSpaces);
21
+ }, [initialSpaces, sort]);
22
+
23
+ return (
24
+ <>
25
+ <header className="max-w-5xl mx-auto w-full max-lg:flex-col items-start flex lg:items-end lg:justify-between gap-4">
26
+ <div>
27
+ <div className="mb-6 font-regular text-xs text-center max-w-max rounded-full border-gray-200 bg-gray-50 border text-gray-700 px-3 py-2 transition-all duration-300">
28
+ <SpaceIcon className="inline-block w-4 h-4 mr-2 drop-shadow-lg" />
29
+ Browse {spaces.length} spaces
30
+ </div>
31
+ <h1 className="font-extrabold text-3xl text-black">
32
+ Zero GPU Spaces
33
+ </h1>
34
+ <p className="text-neutral-500 font-regular text-base">
35
+ Discover spaces with zero GPU usage on 🤗 Hugging Face Spaces.
36
+ </p>
37
+ </div>
38
+ <Sort value={sort} onChange={setSort} />
39
+ </header>
40
+ <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
41
+ {spaces?.map((space: SpaceProps) => (
42
+ <Space key={space.id} space={space} />
43
+ ))}
44
+ </div>
45
+ </>
46
+ );
47
+ };
components/{space.tsx → spaces/space.tsx} RENAMED
File without changes
utils/index.ts CHANGED
@@ -1,3 +1,5 @@
 
 
1
  export const fetchAllPages = async () => {
2
  const filter_key = "zero-a10g";
3
 
@@ -10,5 +12,19 @@ export const fetchAllPages = async () => {
10
  });
11
  const jsonResponses = await Promise.all(urls);
12
  const spaces = jsonResponses.flat()?.filter((space) => space?.runtime?.hardware?.current === filter_key);
13
- return spaces;
14
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { SpaceProps } from "./type";
2
+
3
  export const fetchAllPages = async () => {
4
  const filter_key = "zero-a10g";
5
 
 
12
  });
13
  const jsonResponses = await Promise.all(urls);
14
  const spaces = jsonResponses.flat()?.filter((space) => space?.runtime?.hardware?.current === filter_key);
15
+
16
+
17
+ return sortByCreatedAt(spaces);
18
+ };
19
+
20
+ export const sortByCreatedAt = (spaces: SpaceProps[]) => {
21
+ return spaces.sort((a, b) => {
22
+ return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
23
+ });
24
+ }
25
+
26
+ export const sortByLikes = (spaces: SpaceProps[]) => {
27
+ return spaces.sort((a, b) => {
28
+ return b.likes - a.likes;
29
+ });
30
+ }
utils/type.ts CHANGED
@@ -5,10 +5,11 @@ export interface SpaceProps {
5
  emoji?: string;
6
  runtime: any;
7
  shortDescription?: string;
8
- likes?: number;
9
  authorData: Author;
10
  colorFrom: string;
11
  colorTo: string;
 
12
  }
13
 
14
  interface Author {
 
5
  emoji?: string;
6
  runtime: any;
7
  shortDescription?: string;
8
+ likes: number;
9
  authorData: Author;
10
  colorFrom: string;
11
  colorTo: string;
12
+ createdAt: string;
13
  }
14
 
15
  interface Author {