Noa commited on
Commit
9148f34
·
1 Parent(s): 439098f

Update index.html

Browse files
Files changed (5) hide show
  1. README.md +3 -3
  2. index.html +50 -18
  3. logo.svg +29 -0
  4. script.js +100 -0
  5. style.css +224 -18
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Hugger Roaster
3
- emoji: 💻
4
- colorFrom: indigo
5
- colorTo: red
6
  sdk: static
7
  pinned: false
8
  license: mit
 
1
  ---
2
  title: Hugger Roaster
3
+ emoji: 🧨
4
+ colorFrom: red
5
+ colorTo: gray
6
  sdk: static
7
  pinned: false
8
  license: mit
index.html CHANGED
@@ -1,19 +1,51 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Hugger Roaster</title>
7
+ <link rel="stylesheet" href="style.css" />
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <div class="card">
12
+ <div class="header">
13
+ <img src="logo.svg" alt="logo">
14
+ <p class="subtitle">Roast your favorite Hugging Face user! 👹</p>
15
+ </div>
16
+
17
+ <div id="error-box" class="error-box"></div>
18
+
19
+ <div class="form-group">
20
+ <label class="label">Hugging Face Username</label>
21
+ <div class="input-wrapper">
22
+ <span class="input-prefix">https://huggingface.co/</span>
23
+ <input type="text" id="username-input" placeholder="enzostvs" />
24
+ </div>
25
+ </div>
26
+
27
+ <div class="form-group">
28
+ <label class="label">Language</label>
29
+ <select id="language-select">
30
+ <option value="English">English</option>
31
+ <option value="French">French</option>
32
+ <option value="Spanish">Spanish</option>
33
+ </select>
34
+ </div>
35
+
36
+ <div class="button-container">
37
+ <button id="roast-btn">Roast this Hugger 🔥</button>
38
+ </div>
39
+ </div>
40
+
41
+ <div id="roast-container" class="card roast-container">
42
+ <p class="roast-header">ROASTING</p>
43
+ <p id="roast-text" class="roast-text"></p>
44
+ <button id="share-btn" class="share-btn">Share my roast!</button>
45
+ <div id="share-output" class="share-output"></div>
46
+ </div>
47
+ </div>
48
+
49
+ <script type="module" src="script.js"></script>
50
+ </body>
51
  </html>
logo.svg ADDED
script.js ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
2
+
3
+ let currentRoast = "";
4
+ let currentUsername = "";
5
+
6
+ async function checkUser(username) {
7
+ try {
8
+ const response = await fetch(
9
+ `https://huggingface.co/api/users/${username}/overview`
10
+ );
11
+ return { valid: response.ok };
12
+ } catch {
13
+ return { valid: false };
14
+ }
15
+ }
16
+
17
+ async function roastUser() {
18
+ const username = document.getElementById("username-input").value.trim();
19
+ const language = document.getElementById("language-select").value;
20
+ const errorBox = document.getElementById("error-box");
21
+ const roastBtn = document.getElementById("roast-btn");
22
+ const roastContainer = document.getElementById("roast-container");
23
+ const roastText = document.getElementById("roast-text");
24
+
25
+ errorBox.style.display = "none";
26
+ roastContainer.style.display = "none";
27
+
28
+ if (!username) {
29
+ errorBox.textContent = "Please provide a username";
30
+ errorBox.style.display = "block";
31
+ return;
32
+ }
33
+
34
+ roastBtn.disabled = true;
35
+ roastBtn.textContent = "Roasting in progress...";
36
+ roastBtn.classList.add("animate-pulse");
37
+
38
+ const userCheck = await checkUser(username);
39
+ if (!userCheck.valid) {
40
+ errorBox.textContent = `User '${username}' not found on Hugging Face`;
41
+ errorBox.style.display = "block";
42
+ roastBtn.disabled = false;
43
+ roastBtn.textContent = "Roast this Hugger 🔥";
44
+ roastBtn.classList.remove("animate-pulse");
45
+ return;
46
+ }
47
+
48
+ try {
49
+ const client = await Client.connect("nroggendorff/hugger-roaster-gradio");
50
+ const result = await client.predict("/roast_user", [username, language]);
51
+
52
+ currentRoast = result.data[0];
53
+ currentUsername = username;
54
+
55
+ if (
56
+ currentRoast.startsWith("Error") ||
57
+ currentRoast.startsWith("User") ||
58
+ currentRoast.startsWith("Please")
59
+ ) {
60
+ errorBox.textContent = "⚠️ " + currentRoast;
61
+ errorBox.style.display = "block";
62
+ } else {
63
+ roastText.textContent = currentRoast;
64
+ roastContainer.style.display = "block";
65
+ document.getElementById("share-output").style.display = "none";
66
+ }
67
+ } catch (error) {
68
+ errorBox.textContent = "⚠️ Error generating roast: " + error.message;
69
+ errorBox.style.display = "block";
70
+ }
71
+
72
+ roastBtn.disabled = false;
73
+ roastBtn.textContent = "Roast this Hugger 🔥";
74
+ roastBtn.classList.remove("animate-pulse");
75
+ }
76
+
77
+ async function shareRoast() {
78
+ const shareBtn = document.getElementById("share-btn");
79
+ const shareOutput = document.getElementById("share-output");
80
+
81
+ shareBtn.disabled = true;
82
+ shareBtn.classList.add("animate-pulse");
83
+
84
+ try {
85
+ const client = await Client.connect("nroggendorff/hugger-roaster-gradio");
86
+ const result = { data: ["Not Implemented."] }; //await client.predict("/save_roast", [currentRoast, currentUsername]);
87
+
88
+ shareOutput.textContent = result.data[0];
89
+ shareOutput.style.display = "block";
90
+ } catch (error) {
91
+ shareOutput.textContent = "Error sharing roast: " + error.message;
92
+ shareOutput.style.display = "block";
93
+ }
94
+
95
+ shareBtn.disabled = false;
96
+ shareBtn.classList.remove("animate-pulse");
97
+ }
98
+
99
+ document.getElementById("roast-btn").addEventListener("click", roastUser);
100
+ document.getElementById("share-btn").addEventListener("click", shareRoast);
style.css CHANGED
@@ -1,28 +1,234 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
 
 
 
 
 
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
  .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
28
  }
 
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
  }
6
 
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
9
+ "Ubuntu", "Cantarell", sans-serif;
10
+ background: #f4f4f5;
11
+ min-height: 100vh;
12
+ padding: 1.5rem;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ flex-direction: column;
17
+ gap: 1.5rem;
18
  }
19
 
20
+ .container {
21
+ max-width: 42rem;
22
+ width: 100%;
 
 
23
  }
24
 
25
  .card {
26
+ background: white;
27
+ border: 1px solid #e5e7eb;
28
+ border-radius: 1.5rem;
29
+ padding: 2rem;
30
+ box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.05),
31
+ 0 8px 10px -6px rgb(0 0 0 / 0.05);
32
+ }
33
+
34
+ .header {
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: space-between;
38
+ padding-bottom: 1.25rem;
39
+ border-bottom: 1px solid #e5e7eb;
40
+ margin-bottom: 2rem;
41
+ flex-wrap: wrap;
42
+ gap: 0.5rem;
43
+ }
44
+
45
+ .logo {
46
+ width: 11rem;
47
+ }
48
+
49
+ .subtitle {
50
+ font-size: 0.875rem;
51
+ color: #71717a;
52
+ }
53
+
54
+ .form-group {
55
+ margin-bottom: 1.5rem;
56
+ }
57
+
58
+ .label {
59
+ display: block;
60
+ font-size: 0.75rem;
61
+ font-weight: 600;
62
+ text-transform: uppercase;
63
+ color: #52525b;
64
+ margin-bottom: 0.5rem;
65
+ }
66
+
67
+ .input-wrapper {
68
+ display: flex;
69
+ align-items: center;
70
+ border: 1px solid #e5e7eb;
71
+ border-radius: 0.375rem;
72
+ overflow: hidden;
73
+ transition: all 0.2s;
74
+ }
75
+
76
+ .input-wrapper:focus-within {
77
+ outline: 3px solid rgba(251, 191, 36, 0.2);
78
+ border-color: #fbbf24;
79
+ }
80
+
81
+ .input-prefix {
82
+ background: #f4f4f5;
83
+ border-right: 1px solid #e5e7eb;
84
+ padding: 0.625rem 0.75rem;
85
+ font-size: 0.875rem;
86
+ color: #71717a;
87
+ white-space: nowrap;
88
+ }
89
+
90
+ input[type="text"] {
91
+ flex: 1;
92
+ border: none;
93
+ outline: none;
94
+ padding: 0.625rem 0.75rem;
95
+ font-size: 0.875rem;
96
+ color: #3f3f46;
97
+ }
98
+
99
+ select {
100
+ width: 100%;
101
+ padding: 0.625rem 0.75rem;
102
+ border: 1px solid #e5e7eb;
103
+ border-radius: 0.375rem;
104
+ font-size: 0.875rem;
105
+ color: #3f3f46;
106
+ background: white;
107
+ outline: none;
108
+ transition: all 0.2s;
109
+ }
110
+
111
+ select:focus {
112
+ outline: 3px solid rgba(251, 191, 36, 0.2);
113
+ border-color: #fbbf24;
114
+ }
115
+
116
+ .button-container {
117
+ display: flex;
118
+ justify-content: flex-end;
119
+ }
120
+
121
+ button {
122
+ background: #000;
123
+ color: white;
124
+ border: none;
125
+ border-radius: 9999px;
126
+ padding: 0.625rem 1.25rem;
127
+ font-size: 1rem;
128
+ font-weight: 500;
129
+ cursor: pointer;
130
+ transition: all 0.2s;
131
+ }
132
+
133
+ button:hover:not(:disabled) {
134
+ background: #27272a;
135
+ }
136
+
137
+ button:disabled {
138
+ background: #d4d4d8;
139
+ color: #71717a;
140
+ cursor: not-allowed;
141
+ }
142
+
143
+ button.animate-pulse {
144
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
145
+ }
146
+
147
+ @keyframes pulse {
148
+ 0%,
149
+ 100% {
150
+ opacity: 1;
151
+ }
152
+ 50% {
153
+ opacity: 0.5;
154
+ }
155
+ }
156
+
157
+ .error-box {
158
+ display: none;
159
+ background: rgba(239, 68, 68, 0.1);
160
+ border: 1px solid rgba(239, 68, 68, 0.15);
161
+ color: #dc2626;
162
+ padding: 0.875rem;
163
+ border-radius: 0.75rem;
164
+ font-size: 0.875rem;
165
+ margin-bottom: 1.5rem;
166
+ }
167
+
168
+ .roast-container {
169
+ display: none;
170
+ position: relative;
171
+ overflow: hidden;
172
+ }
173
+
174
+ .roast-container::before {
175
+ content: "🧨";
176
+ position: absolute;
177
+ bottom: -3rem;
178
+ right: 0;
179
+ font-size: 8rem;
180
+ opacity: 0.2;
181
+ z-index: 0;
182
+ pointer-events: none;
183
+ }
184
+
185
+ .roast-header {
186
+ font-size: 1rem;
187
+ font-weight: 600;
188
+ text-transform: uppercase;
189
+ letter-spacing: 0.05em;
190
+ margin-bottom: 0.5rem;
191
+ position: relative;
192
+ z-index: 1;
193
+ }
194
+
195
+ .roast-text {
196
+ font-size: 1.125rem;
197
+ line-height: 1.75;
198
+ color: #6b7280;
199
+ white-space: pre-wrap;
200
+ position: relative;
201
+ z-index: 1;
202
+ margin-bottom: 1.25rem;
203
+ }
204
+
205
+ .share-btn {
206
+ margin-top: 1rem;
207
+ }
208
+
209
+ .share-output {
210
+ display: none;
211
+ margin-top: 1.25rem;
212
+ padding: 0.75rem;
213
+ background: #f4f4f5;
214
+ border-radius: 0.5rem;
215
+ font-size: 0.875rem;
216
+ color: #3f3f46;
217
+ }
218
+
219
+ @media (max-width: 640px) {
220
+ .header {
221
+ flex-direction: column;
222
+ align-items: flex-start;
223
+ }
224
+ .input-prefix {
225
+ font-size: 0.75rem;
226
+ }
227
+ button {
228
+ width: 100%;
229
+ }
230
  }
231
 
232
+ #language-select {
233
+ max-width: 150px;
234
  }