Wavetype commited on
Commit
584ea9d
·
verified ·
1 Parent(s): d2ac47d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +255 -19
index.html CHANGED
@@ -1,19 +1,255 @@
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>Fantasy Rally: Card Architect</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <style>
10
+ .card-foil {
11
+ background: linear-gradient(135deg, rgba(255,255,255,0.4) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.4) 100%);
12
+ background-size: 200% 200%;
13
+ animation: shine 3s infinite linear;
14
+ }
15
+ @keyframes shine {
16
+ 0% { background-position: -200% -200%; }
17
+ 100% { background-position: 200% 200%; }
18
+ }
19
+ #three-container canvas {
20
+ border-radius: 1rem;
21
+ cursor: grab;
22
+ }
23
+ #three-container canvas:active {
24
+ cursor: grabbing;
25
+ }
26
+ </style>
27
+ </head>
28
+ <body class="bg-slate-900 text-white font-sans p-8">
29
+
30
+ <div class="max-w-7xl mx-auto grid grid-cols-1 lg:grid-cols-2 gap-8">
31
+
32
+ <div class="space-y-6">
33
+ <header>
34
+ <h1 class="text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500">
35
+ Fantasy Rally: Card Architect
36
+ </h1>
37
+ <p class="text-slate-400">Manage car customizer rewards and rarities.</p>
38
+ </header>
39
+
40
+ <div class="bg-slate-800 rounded-xl p-6 border border-slate-700">
41
+ <div class="flex justify-between mb-4">
42
+ <h2 class="text-xl font-semibold">Reward Inventory</h2>
43
+ <div class="space-x-2">
44
+ <button onclick="selectAll()" class="text-xs bg-slate-700 px-3 py-1 rounded hover:bg-slate-600">Select All</button>
45
+ <button onclick="exportSQL()" class="text-xs bg-green-600 px-3 py-1 rounded hover:bg-green-500 font-bold">Export SQL</button>
46
+ </div>
47
+ </div>
48
+
49
+ <div class="overflow-x-auto max-h-96 overflow-y-auto">
50
+ <table id="rewardTable" class="w-full text-left text-sm">
51
+ <thead class="bg-slate-900 sticky top-0">
52
+ <tr>
53
+ <th class="p-2"><input type="checkbox" id="masterCheck" onclick="toggleAll(this)"></th>
54
+ <th class="p-2">Title</th>
55
+ <th class="p-2">Description</th>
56
+ <th class="p-2">Rarity/Color</th>
57
+ <th class="p-2">Actions</th>
58
+ </tr>
59
+ </thead>
60
+ <tbody id="tableBody">
61
+ </tbody>
62
+ </table>
63
+ </div>
64
+
65
+ <button onclick="addRow()" class="mt-4 w-full py-2 bg-blue-600 rounded-lg hover:bg-blue-500 transition-colors">+ Add New Card</button>
66
+ </div>
67
+ </div>
68
+
69
+ <div class="sticky top-8 h-fit">
70
+ <div class="bg-slate-800 rounded-xl p-6 border border-slate-700 flex flex-col items-center">
71
+ <h2 class="text-xl font-semibold mb-4 w-full">3D Card Viewer</h2>
72
+ <div id="three-container" class="w-full aspect-[3/4] bg-black rounded-lg overflow-hidden shadow-2xl relative">
73
+ <div id="loadingOverlay" class="absolute inset-0 flex items-center justify-center bg-slate-900 z-10 hidden">
74
+ <span>Rendering HD Foil...</span>
75
+ </div>
76
+ </div>
77
+ <div class="mt-4 text-center text-slate-400 text-sm italic">
78
+ Drag to rotate on X-Axis | Click card to reset view
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+
84
+ <script>
85
+ let rewards = [
86
+ { id: 1, title: "Neon Underglow", desc: "Cyberpunk aesthetic pulses.", color: "#3b82f6", rarity: "Rare", selected: false },
87
+ { id: 2, title: "Quantum Turbo", desc: "Breaks the sound barrier.", color: "#a855f7", rarity: "Legendary", selected: false }
88
+ ];
89
+
90
+ let scene, camera, renderer, cardMesh, foilMesh;
91
+ let isRotating = true;
92
+
93
+ function init3D() {
94
+ const container = document.getElementById('three-container');
95
+ scene = new THREE.Scene();
96
+ camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 1000);
97
+ renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
98
+ renderer.setSize(container.clientWidth, container.clientHeight);
99
+ container.appendChild(renderer.domElement);
100
+
101
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.8);
102
+ scene.add(ambientLight);
103
+
104
+ const pointLight = new THREE.PointLight(0xffffff, 1);
105
+ pointLight.position.set(5, 5, 5);
106
+ scene.add(pointLight);
107
+
108
+ createCard(rewards[0]);
109
+ camera.position.z = 5;
110
+ animate();
111
+ }
112
+
113
+ function createCard(data) {
114
+ if (cardMesh) scene.remove(cardMesh);
115
+ if (foilMesh) scene.remove(foilMesh);
116
+
117
+ const geometry = new THREE.BoxGeometry(2.5, 3.5, 0.1);
118
+ const material = new THREE.MeshStandardMaterial({ color: data.color });
119
+ cardMesh = new THREE.Mesh(geometry, material);
120
+
121
+ // Foil Layer for Legendary/Epic
122
+ if (data.rarity === "Legendary") {
123
+ const foilGeo = new THREE.PlaneGeometry(2.4, 3.4);
124
+ const foilMat = new THREE.MeshPhongMaterial({
125
+ color: 0xffffff,
126
+ specular: 0xffffff,
127
+ shininess: 100,
128
+ transparent: true,
129
+ opacity: 0.3
130
+ });
131
+ foilMesh = new THREE.Mesh(foilGeo, foilMat);
132
+ foilMesh.position.z = 0.06;
133
+ cardMesh.add(foilMesh);
134
+ }
135
+
136
+ scene.add(cardMesh);
137
+ }
138
+
139
+ function animate() {
140
+ requestAnimationFrame(animate);
141
+ if (cardMesh && isRotating) {
142
+ cardMesh.rotation.y += 0.01;
143
+ }
144
+ renderer.render(scene, camera);
145
+ }
146
+
147
+ // Table Logic
148
+ function renderTable() {
149
+ const tbody = document.getElementById('tableBody');
150
+ tbody.innerHTML = '';
151
+ rewards.forEach((reward, index) => {
152
+ const tr = document.createElement('tr');
153
+ tr.className = "border-b border-slate-700 hover:bg-slate-700/50 transition-colors cursor-pointer";
154
+ tr.onclick = (e) => {
155
+ if(e.target.tagName !== 'INPUT' && e.target.tagName !== 'BUTTON') previewCard(index);
156
+ };
157
+
158
+ tr.innerHTML = `
159
+ <td class="p-2"><input type="checkbox" ${reward.selected ? 'checked' : ''} onchange="toggleSelect(${index})"></td>
160
+ <td class="p-2"><input class="bg-transparent border-none focus:ring-1 ring-blue-500 rounded px-1" value="${reward.title}" onchange="updateReward(${index}, 'title', this.value)"></td>
161
+ <td class="p-2"><input class="bg-transparent border-none focus:ring-1 ring-blue-500 rounded px-1" value="${reward.desc}" onchange="updateReward(${index}, 'desc', this.value)"></td>
162
+ <td class="p-2">
163
+ <select class="bg-slate-900 border-none text-xs rounded" onchange="updateReward(${index}, 'rarity', this.value)">
164
+ <option value="Common" ${reward.rarity === 'Common' ? 'selected' : ''}>Common</option>
165
+ <option value="Rare" ${reward.rarity === 'Rare' ? 'selected' : ''}>Rare</option>
166
+ <option value="Legendary" ${reward.rarity === 'Legendary' ? 'selected' : ''}>Legendary</option>
167
+ </select>
168
+ <input type="color" value="${reward.color}" onchange="updateReward(${index}, 'color', this.value)" class="w-6 h-6 bg-transparent border-none">
169
+ </td>
170
+ <td class="p-2">
171
+ <button onclick="deleteRow(${index})" class="text-red-400 hover:text-red-300">✕</button>
172
+ </td>
173
+ `;
174
+ tbody.appendChild(tr);
175
+ });
176
+ }
177
+
178
+ function addRow() {
179
+ rewards.push({ id: Date.now(), title: "New Item", desc: "Add description...", color: "#64748b", rarity: "Common", selected: false });
180
+ renderTable();
181
+ }
182
+
183
+ function deleteRow(index) {
184
+ rewards.splice(index, 1);
185
+ renderTable();
186
+ }
187
+
188
+ function updateReward(index, field, value) {
189
+ rewards[index][field] = value;
190
+ if (field === 'color' || field === 'rarity') previewCard(index);
191
+ }
192
+
193
+ function toggleSelect(index) {
194
+ rewards[index].selected = !rewards[index].selected;
195
+ }
196
+
197
+ function toggleAll(master) {
198
+ rewards.forEach(r => r.selected = master.checked);
199
+ renderTable();
200
+ }
201
+
202
+ function selectAll() {
203
+ rewards.forEach(r => r.selected = true);
204
+ document.getElementById('masterCheck').checked = true;
205
+ renderTable();
206
+ }
207
+
208
+ function previewCard(index) {
209
+ const data = rewards[index];
210
+ createCard(data);
211
+ }
212
+
213
+ function exportSQL() {
214
+ const selected = rewards.filter(r => r.selected);
215
+ if (selected.length === 0) return alert("Select cards to export.");
216
+
217
+ let sql = "INSERT INTO fantasy_rally_cards (title, description, rarity, hex_color) VALUES \n";
218
+ const values = selected.map(r => `('${r.title}', '${r.desc}', '${r.rarity}', '${r.color}')`).join(",\n");
219
+
220
+ const blob = new Blob([sql + values + ";"], { type: 'text/sql' });
221
+ const url = window.URL.createObjectURL(blob);
222
+ const a = document.createElement('a');
223
+ a.href = url;
224
+ a.download = "cards_export.sql";
225
+ a.click();
226
+ }
227
+
228
+ // Mouse Rotation Logic
229
+ let isDragging = false;
230
+ let previousMouseX = 0;
231
+
232
+ const container = document.getElementById('three-container');
233
+ container.addEventListener('mousedown', (e) => {
234
+ isDragging = true;
235
+ isRotating = false;
236
+ previousMouseX = e.clientX;
237
+ });
238
+ window.addEventListener('mouseup', () => { isDragging = false; });
239
+ window.addEventListener('mousemove', (e) => {
240
+ if (isDragging && cardMesh) {
241
+ const deltaX = e.clientX - previousMouseX;
242
+ cardMesh.rotation.y += deltaX * 0.01;
243
+ previousMouseX = e.clientX;
244
+ }
245
+ });
246
+ container.addEventListener('click', () => { isRotating = !isRotating; });
247
+
248
+ // Initialize
249
+ window.onload = () => {
250
+ renderTable();
251
+ init3D();
252
+ };
253
+ </script>
254
+ </body>
255
+ </html>