"
A form component to set your profile picture, display name, email address, and country. You should be able to select if your account is public or private. The form should include a submit button and validation. [Generated in a neobrutal app]
"
// A form component to set your profile picture, display name, email address, and country. You should be able to select if your account is public or private. The form should include a submit button and validation.
import React, { useState } from 'react';
import { User, Upload } from 'lucide-react';
import Input from './ui/Input';
import Button from './ui/Button';
import Select from './ui/Select';
const ProfileForm = () => {
const [displayName, setDisplayName] = useState('');
const [email, setEmail] = useState('');
const [country, setCountry] = useState('');
const [isPublic, setIsPublic] = useState(true);
const [profilePicture, setProfilePicture] = useState(null);
const [errors, setErrors] = useState({});
const countries = ['United States', 'Canada', 'United Kingdom', 'Australia', 'Germany', 'France', 'Japan'];
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = {};
if (!displayName.trim()) newErrors.displayName = 'Display name is required';
if (!email.trim()) newErrors.email = 'Email is required';
else if (!/\S+@\S+\.\S+/.test(email)) newErrors.email = 'Email is invalid';
if (!country) newErrors.country = 'Country is required';
if (Object.keys(newErrors).length === 0) {
// Submit form data
console.log('Form submitted:', { displayName, email, country, isPublic, profilePicture });
} else {
setErrors(newErrors);
}
};
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
setProfilePicture(URL.createObjectURL(file));
}
};
return (
<div className="w-[400px] max-w-md mx-auto mt-10 p-6 border-2 border-border dark:border-darkBorder rounded-base bg-bg dark:bg-darkBg shadow-light dark:shadow-dark">
<h2 className="text-2xl font-heading mb-6 text-text dark:text-darkText">Profile Settings</h2>
<form onSubmit={handleSubmit}>
<div className="mb-6">
<div className="w-32 h-32 mx-auto">
<div className="relative h-full">
{profilePicture ? (
<img src={profilePicture} alt="Profile" className="w-full h-full object-cover rounded-full" />
) : (
<div className="w-full h-full bg-main rounded-full flex items-center justify-center">
<User className="w-12 h-12 text-text dark:text-darkText" />
</div>
)}
<label htmlFor="profile-picture" className="absolute bottom-0 right-0 bg-main p-2 rounded-full cursor-pointer">
<Upload className="w-4 h-4 text-text dark:text-darkText" />
</label>
<input
id="profile-picture"
type="file"
accept="image/*"
onChange={handleFileChange}
className="hidden"
/>
</div>
</div>
</div>
<div className="mb-4">
<label htmlFor="display-name" className="block mb-2 font-base text-text dark:text-darkText">Display Name</label>
<Input
className="w-full"
value={displayName}
setValue={setDisplayName}
placeholder="Enter your display name"
/>
{errors.displayName && <p className="text-red-500 text-sm mt-1">{errors.displayName}</p>}
</div>
<div className="mb-4">
<label htmlFor="email" className="block mb-2 font-base text-text dark:text-darkText">Email Address</label>
<Input
className="w-full"
value={email}
setValue={setEmail}
placeholder="Enter your email address"
/>
{errors.email && <p className="text-red-500 text-sm mt-1">{errors.email}</p>}
</div>
<div className="mb-4">
<label htmlFor="country" className="block mb-2 font-base text-text dark:text-darkText">Country</label>
<Select
items={countries}
onChange={(selectedCountry) => setCountry(selectedCountry)}
value={country}
/>
{errors.country && <p className="text-red-500 text-sm mt-1">{errors.country}</p>}
</div>
<div className="mb-6">
<label className="flex items-center cursor-pointer">
<div className="relative">
<input
type="checkbox"
className="sr-only"
checked={isPublic}
onChange={() => setIsPublic(!isPublic)}
/>
<div className={`block w-14 h-8 rounded-full ${isPublic ? 'bg-main' : 'bg-gray-600'}`}></div>
<div className={`dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition ${isPublic ? 'transform translate-x-6' : ''}`}></div>
</div>
<div className="ml-3 text-text dark:text-darkText font-base">
{isPublic ? 'Public Account' : 'Private Account'}
</div>
</label>
</div>
<Button
onClick={handleSubmit}
className="w-full justify-center"
>
Save Profile
</Button>
</form>
</div>
);
};
export default ProfileForm;
// Weather card that displays weather and a suggestion of what to wear at a zip code
import React, { useState } from 'react';
import { CloudSun, Thermometer, Wind, Drop, MapPin } from '@phosphor-icons/react/dist/ssr';
import Button from '@/components/ion/Button';
import Input from '@/components/ion/Input';
import { motion } from "framer-motion";
import Divider from './ion/Divider';
const sampleWeatherData = {
city: 'Toronto',
temperature: 20,
condition: 'Sunny',
feelsLike: 22,
windSpeed: 10,
humidity: 50,
};
const WeatherCard = () => {
const [zipCode, setZipCode] = useState('');
const [weather, setWeather] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const fetchWeather = async () => {
setLoading(true);
setError('');
try {
// Replace with actual API call
// const response = await fetch(`https://api.example.com/weather/${zipCode}`);
// const data = await response.json();
// setWeather(data);
setWeather(sampleWeatherData);
} catch (err) {
setError('Failed to fetch weather data');
} finally {
setLoading(false);
}
};
const getClothingSuggestion = (temperature) => {
if (temperature > 25) return 'Light clothing, shorts, and t-shirt';
if (temperature > 15) return 'Light jacket or sweater';
if (temperature > 5) return 'Warm coat and layers';
return 'Heavy winter coat, scarf, and gloves';
};
return (
<div className="bg-background w-[400px] flex flex-col gap-5 p-6 rounded-radius-md shadow-medium">
<div className="flex items-center gap-2">
<Input
placeholder="Enter ZIP code"
value={zipCode}
onChange={(e) => setZipCode(e.target.value)}
className="flex-grow"
iconLeading={<MapPin size={16} weight="bold" />}
/>
<Button
variant="filled"
color="primary"
size="md"
onClick={fetchWeather}
disabled={loading || !zipCode}
>
{loading ? 'Loading...' : 'Get Weather'}
</Button>
</div>
{error && <div className="text-danger text-sm">{error}</div>}
{weather && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
className="flex flex-col gap-4"
>
<div className="flex items-center justify-between">
<div className="text-2xl font-semibold text-foreground">{weather.city}</div>
<div className="text-4xl font-bold text-primary">{weather.temperature}°C</div>
</div>
<div className="flex justify-between text-secondary">
<div className="flex items-center gap-2">
<CloudSun size={20} />
<span>{weather.condition}</span>
</div>
<div className="flex items-center gap-2">
<Thermometer size={20} />
<span>{weather.feelsLike}°C</span>
</div>
</div>
<div className="flex justify-between text-secondary">
<div className="flex items-center gap-2">
<Wind size={20} />
<span>{weather.windSpeed} km/h</span>
</div>
<div className="flex items-center gap-2">
<Drop size={20} />
<span>{weather.humidity}%</span>
</div>
</div>
<Divider />
<div className="text-foreground">
<div className="font-semibold mb-2">What to Wear:</div>
<div>{getClothingSuggestion(weather.temperature)}</div>
</div>
</motion.div>
)}
</div>
);
};
export default WeatherCard;
// A card that displays the relevant statistics of a basketball player, their photo, their current team, age, and origin. You should be able to click the card to expand more info.
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { ChevronDown, ChevronUp } from 'lucide-react';
const PlayerCard = ({ player }) => {
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpand = () => {
setIsExpanded(!isExpanded);
};
return (
<motion.div
className="glass dark:glass-dark p-6 rounded-xl shadow-lg text-white max-w-md mx-auto cursor-pointer"
onClick={toggleExpand}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
<div className="flex items-center mb-4">
<img src={player.photo} alt={player.name} className="w-24 h-24 rounded-full mr-4 object-cover" />
<div>
<h2 className="text-2xl font-semibold">{player.name}</h2>
<p className="text-gray-300">{player.team}</p>
</div>
</div>
<div className="grid grid-cols-2 gap-4 mb-4">
<div>
<p className="text-gray-400">Age</p>
<p className="text-xl">{player.age}</p>
</div>
<div>
<p className="text-gray-400">Origin</p>
<p className="text-xl">{player.origin}</p>
</div>
</div>
<div className="grid grid-cols-3 gap-4 mb-4">
<div>
<p className="text-gray-400">PPG</p>
<p className="text-xl">{player.stats.ppg}</p>
</div>
<div>
<p className="text-gray-400">RPG</p>
<p className="text-xl">{player.stats.rpg}</p>
</div>
<div>
<p className="text-gray-400">APG</p>
<p className="text-xl">{player.stats.apg}</p>
</div>
</div>
<AnimatePresence>
{isExpanded && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.3 }}
>
<div className="mt-4 pt-4 border-t border-gray-600">
<h3 className="text-xl font-semibold mb-2">Additional Info</h3>
<p className="text-gray-300 mb-2">Height: {player.height}</p>
<p className="text-gray-300 mb-2">Weight: {player.weight}</p>
<p className="text-gray-300 mb-2">Position: {player.position}</p>
<p className="text-gray-300">Draft: {player.draft}</p>
</div>
</motion.div>
)}
</AnimatePresence>
<div className="flex justify-center mt-4">
{isExpanded ? (
<ChevronUp className="text-gray-400" />
) : (
<ChevronDown className="text-gray-400" />
)}
</div>
</motion.div>
);
};
const BasketballPlayerStats = () => {
const playerData = {
name: "LeBron James",
photo: "https://hoopshype.com/wp-content/uploads/sites/92/2024/02/i_54_cf_2e_lebron-james.png?w=1000&h=600&crop=1",
team: "Los Angeles Lakers",
age: 36,
origin: "Akron, Ohio",
stats: {
ppg: 25.0,
rpg: 7.7,
apg: 7.8
},
height: "6'9\"",
weight: "250 lbs",
position: "Small Forward",
draft: "2003 Round 1 Pick 1"
};
return (
<div className="p-4">
<PlayerCard player={playerData} />
</div>
);
};
export default BasketballPlayerStats;
// A kanban board component with 3 columns, "backlog", "in progress", and "done". Each column should have task cards with a title of the task and other information. You should be able to drag and drop from one column to another.
import React, { useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
const initialTasks = {
backlog: [
{ id: 'task-1', title: 'Create login page', description: 'Implement user authentication' },
{ id: 'task-2', title: 'Design database schema', description: 'Plan out data structure' },
],
inProgress: [
{ id: 'task-3', title: 'Develop API endpoints', description: 'Create RESTful API for the application' },
],
done: [
{ id: 'task-4', title: 'Set up project repository', description: 'Initialize Git repo and invite team members' },
],
};
const KanbanBoard = () => {
const [tasks, setTasks] = useState(initialTasks);
const onDragEnd = (result) => {
const { source, destination } = result;
if (!destination) return;
const sourceColumn = tasks[source.droppableId];
const destColumn = tasks[destination.droppableId];
const [removed] = sourceColumn.splice(source.index, 1);
destColumn.splice(destination.index, 0, removed);
setTasks({
...tasks,
[source.droppableId]: sourceColumn,
[destination.droppableId]: destColumn,
});
};
return (
<div className="nes-container with-title is-dark p-4 max-w-6xl mx-auto mt-10">
<p className="title">Kanban Board</p>
<DragDropContext onDragEnd={onDragEnd}>
<div className="flex justify-between space-x-4">
{Object.keys(tasks).map((columnId) => (
<div key={columnId} className="flex-1">
<h2 className="text-lg font-bold mb-2 capitalize">{columnId}</h2>
<Droppable droppableId={columnId}>
{(provided) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
className="nes-container is-rounded min-h-[300px]"
>
{tasks[columnId].map((task, index) => (
<Draggable key={task.id} draggableId={task.id} index={index}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className="nes-container is-rounded mb-2 bg-white text-black"
>
<h3 className="font-bold">{task.title}</h3>
<p className="text-sm">{task.description}</p>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</div>
))}
</div>
</DragDropContext>
</div>
);
};
export default KanbanBoard;