1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// This approach will create a Tinder-like swiping interface for profiles.
// We'll use React for the frontend, and Val Town's SQLite for persistence.
// The server will serve the initial HTML and handle API requests for fetching and updating profiles.
/** @jsxImportSource https://esm.sh/react */
import React, { useState, useEffect } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
import { motion, AnimatePresence } from "https://esm.sh/framer-motion";
function App() {
const [profiles, setProfiles] = useState([]);
const [currentIndex, setCurrentIndex] = useState(0);
const [newProfile, setNewProfile] = useState({ username: '', image_url: '', link: '', followers: '' });
const [message, setMessage] = useState('');
useEffect(() => {
fetchProfiles();
addSampleProfiles(); // Add this line
}, []);
const fetchProfiles = async () => {
const response = await fetch('/profiles');
const data = await response.json();
setProfiles(data);
};
const addSampleProfiles = async () => {
await fetch('/add-sample-profiles', {
method: 'POST',
});
fetchProfiles(); // Fetch profiles again after adding samples
};
const clearDatabase = async () => {
await fetch('/clear-database', { method: 'POST' });
setProfiles([]);
setCurrentIndex(0);
setMessage('Database cleared');
};
const handleInputChange = (e) => {
setNewProfile({ ...newProfile, [e.target.name]: e.target.value });
};
const addNewProfile = async (e) => {
e.preventDefault();
const response = await fetch('/add-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newProfile),
});
if (response.ok) {
setMessage('New profile added');
setNewProfile({ username: '', image_url: '', link: '', followers: '' });
fetchProfiles();
} else {
setMessage('Failed to add new profile');
}
};
if (profiles.length === 0) {
return <div className="app"><h1>Loading profiles...</h1></div>;
}
const handleSwipe = async (direction) => {
if (currentIndex >= profiles.length) return;
const profile = profiles[currentIndex];
const response = await fetch('/swipe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: profile.id, direction }),
});
setCurrentIndex(currentIndex + 1);
if (direction === 'left') {
setProfiles(profiles.filter(p => p.id !== profile.id));
}
};
const currentProfile = profiles[currentIndex];
return (
<div className="app">
<h1>Profile Swiper</h1>
<AnimatePresence>
{currentProfile && (
<motion.div
key={currentProfile.id}
className="profile-card"
initial={{ x: 300, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
exit={{ x: -300, opacity: 0 }}
>
<div className="profile-card-content">
<img
src={currentProfile.image_url}
alt={currentProfile.username}