anzorq commited on
Commit
8316e17
β€’
1 Parent(s): ee72882

+loading animation

Browse files
Files changed (1) hide show
  1. pages/index.js +89 -54
pages/index.js CHANGED
@@ -1,7 +1,6 @@
1
  import { Inter } from 'next/font/google';
2
  import SearchBar from '@/components/searchBar';
3
  import Card from '@/components/card';
4
- import BackgroundEmojiGrid from '@/components/backgroundEmojiGrid';
5
  import { predict } from '@/pages/api/api_hf';
6
  import { get_space_info } from '@/pages/api/hf_space';
7
  import { useState, useEffect } from 'react';
@@ -10,21 +9,22 @@ const inter = Inter({ subsets: ['latin'] });
10
 
11
  export default function Home() {
12
  const [spaceInfo, setSpaceInfo] = useState(null);
 
13
  const [searchResults, setSearchResults] = useState([]);
 
 
14
 
15
  useEffect(() => {
16
  async function fetchSpaceInfo(results) {
17
- const spacePromises = results.map(async (result) => {
18
- const [id, description] = result;
19
- const space = await get_space_info(id);
20
- if (space === null) {
21
- return null;
22
- }
23
- space.description = description;
24
- return space;
25
- });
26
- const spaceData = await Promise.all(spacePromises);
27
  setSpaceInfo(spaceData);
 
28
  document.querySelector('.search-bar').scrollIntoView({
29
  behavior: 'smooth',
30
  block: 'start',
@@ -38,60 +38,95 @@ export default function Home() {
38
  }
39
  }, [searchResults]);
40
 
41
- async function onSearch(query) {
42
- if (query === '') {
43
- setSearchResults([]);
44
- return;
45
  }
46
- const results = await predict(query, 12);
47
- setSearchResults(results);
 
 
 
 
48
  }
49
 
50
  useEffect(() => {
51
- const focusSearchBar = () => {
52
- document.querySelector('.search-bar').focus();
53
- };
54
-
55
- focusSearchBar();
56
  }, []);
57
 
 
 
 
 
58
  return (
59
  <main className={`flex min-h-screen flex-col items-center p-8 md:px-24 pt-20 bg-gray-950 ${inter.className} justify-between`}>
60
- {/* <BackgroundEmojiGrid /> */}
61
  <h1 className="text-4xl md:text-6xl font-bold text-center mb-12 text-white">πŸ€— Hugging Face Spaces</h1>
62
  <SearchBar onSearch={onSearch} />
63
- {spaceInfo !== null && (
64
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 w-full mt-8">
65
- {spaceInfo.map((space, index) => space && (
66
- <Card
67
- key={index}
68
- space_id={space.space_id}
69
- author={space.author}
70
- title={space.title}
71
- description={space.description}
72
- emoji={space.emoji}
73
- lastModified={space.lastModified}
74
- colorFrom={space.colorFrom}
75
- colorTo={space.colorTo}
76
- likes={space.likes}
77
- sdk={space.sdk}
78
- runtimeStage={space.runtime_stage}
79
- currentHardware={space.current_hardware}
80
- />
81
- ))}
82
- </div>
83
- )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  <footer className="text-center text-gray-500 text-sm mt-8 bottom-0 w-full p-4">
85
- Created by Anzor Qunash
86
- <br />
87
- <a href="https://huggingface.co/datasets/anzorq/hf-spaces-descriptions-embeddings" target="_blank" rel="noopener noreferrer">Dataset</a>
88
- <span className="mx-2">β€’</span>
89
- <a href="https://github.com/qunash" target="_blank" rel="noopener noreferrer">GitHub</a>
90
- <span className="mx-2">β€’</span>
91
- <a href="https://twitter.com/hahahahohohe" target="_blank" rel="noopener noreferrer">Twitter</a>
92
- <span className="mx-2">β€’</span>
93
- <a href="https://www.buymeacoffee.com/anzorq" target="_blank" rel="noopener noreferrer">Buy me a coffee</a>
 
 
 
 
 
 
 
 
94
  </footer>
95
  </main>
96
  );
97
- }
 
1
  import { Inter } from 'next/font/google';
2
  import SearchBar from '@/components/searchBar';
3
  import Card from '@/components/card';
 
4
  import { predict } from '@/pages/api/api_hf';
5
  import { get_space_info } from '@/pages/api/hf_space';
6
  import { useState, useEffect } from 'react';
 
9
 
10
  export default function Home() {
11
  const [spaceInfo, setSpaceInfo] = useState(null);
12
+ const [sortedSpaceInfo, setSortedSpaceInfo] = useState(null);
13
  const [searchResults, setSearchResults] = useState([]);
14
+ const [isLoading, setIsLoading] = useState(false);
15
+ const [sortBy, setSortBy] = useState('relevance');
16
 
17
  useEffect(() => {
18
  async function fetchSpaceInfo(results) {
19
+ setIsLoading(true);
20
+ const spaceData = await Promise.all(
21
+ results.map(async ([id, description]) => {
22
+ const space = await get_space_info(id);
23
+ return space ? { ...space, description } : null;
24
+ })
25
+ );
 
 
 
26
  setSpaceInfo(spaceData);
27
+ setIsLoading(false);
28
  document.querySelector('.search-bar').scrollIntoView({
29
  behavior: 'smooth',
30
  block: 'start',
 
38
  }
39
  }, [searchResults]);
40
 
41
+ useEffect(() => {
42
+ if (spaceInfo) {
43
+ setSortedSpaceInfo(sortResults(spaceInfo, sortBy));
 
44
  }
45
+ }, [spaceInfo, sortBy]);
46
+
47
+ async function onSearch(query) {
48
+ setIsLoading(true); // Show loading animation when searching
49
+ setSortBy('relevance'); // Reset sorting to Relevance on new search
50
+ setSearchResults(query ? await predict(query, 12) : []);
51
  }
52
 
53
  useEffect(() => {
54
+ document.querySelector('.search-bar')?.focus();
 
 
 
 
55
  }, []);
56
 
57
+ function sortResults(results, sortBy) {
58
+ return sortBy === 'likes' ? [...results].sort((a, b) => b.likes - a.likes) : results;
59
+ }
60
+
61
  return (
62
  <main className={`flex min-h-screen flex-col items-center p-8 md:px-24 pt-20 bg-gray-950 ${inter.className} justify-between`}>
 
63
  <h1 className="text-4xl md:text-6xl font-bold text-center mb-12 text-white">πŸ€— Hugging Face Spaces</h1>
64
  <SearchBar onSearch={onSearch} />
65
+ { isLoading ? (
66
+ <div className="col-span-full flex justify-center items-center">
67
+ <div className="animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-white"></div>
68
+ </div>
69
+ ) : (
70
+ sortedSpaceInfo && (
71
+ <>
72
+ {!isLoading && (
73
+ <div className="flex justify-center mt-4 items-baseline">
74
+ <span className="text-white mr-2">Sort by:</span>
75
+ {['relevance', 'likes'].map((option) => (
76
+ <button
77
+ key={option}
78
+ className={`px-4 py-1 rounded-full mr-2 ${sortBy === option ? 'bg-white text-gray-900' : 'bg-gray-900 text-white'}`}
79
+ onClick={() => setSortBy(option)}
80
+ >
81
+ {option.charAt(0).toUpperCase() + option.slice(1)}
82
+ </button>
83
+ ))}
84
+ </div>
85
+ )}
86
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 w-full mt-8">
87
+ {
88
+ sortedSpaceInfo.map(
89
+ (space, index) =>
90
+ space && (
91
+ <Card
92
+ key={index}
93
+ {...space}
94
+ space_id={space.space_id}
95
+ author={space.author}
96
+ title={space.title}
97
+ emoji={space.emoji}
98
+ lastModified={space.lastModified}
99
+ colorFrom={space.colorFrom}
100
+ colorTo={space.colorTo}
101
+ sdk={space.sdk}
102
+ runtimeStage={space.runtime_stage}
103
+ currentHardware={space.current_hardware}
104
+ />
105
+ )
106
+ )
107
+ }
108
+ </div>
109
+ </>
110
+ ))}
111
  <footer className="text-center text-gray-500 text-sm mt-8 bottom-0 w-full p-4">
112
+ Created by Anzor Qunash
113
+ <br />
114
+ <a href="https://huggingface.co/datasets/anzorq/hf-spaces-descriptions-embeddings" target="_blank" rel="noopener noreferrer">
115
+ Dataset
116
+ </a>
117
+ <span className="mx-2">β€’</span>
118
+ <a href="https://github.com/qunash" target="_blank" rel="noopener noreferrer">
119
+ GitHub
120
+ </a>
121
+ <span className="mx-2">β€’</span>
122
+ <a href="https://twitter.com/hahahahohohe" target="_blank" rel="noopener noreferrer">
123
+ Twitter
124
+ </a>
125
+ <span className="mx-2">β€’</span>
126
+ <a href="https://www.buymeacoffee.com/anzorq" target="_blank" rel="noopener noreferrer">
127
+ Buy me a coffee
128
+ </a>
129
  </footer>
130
  </main>
131
  );
132
+ }