180 lines
5.5 KiB
JavaScript
180 lines
5.5 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
|
|
/**
|
|
* Główny komponent aplikacji React.
|
|
* Zmodyfikowany w celu zapewnienia pełnej funkcjonalności zarządzania zadaniami
|
|
* z nowoczesnym interfejsem użytkownika i obsługą stanu.
|
|
*/
|
|
const App = () => {
|
|
const [tasks, setTasks] = useState([
|
|
{ id: 1, text: 'Zainstalować zależności', completed: true },
|
|
{ id: 2, text: 'Zaimplementować logikę biznesową', completed: false }
|
|
]);
|
|
const [inputValue, setInputValue] = useState('');
|
|
|
|
const handleAddTask = (e) => {
|
|
e.preventDefault();
|
|
if (inputValue.trim() === '') return;
|
|
|
|
const newTask = {
|
|
id: Date.now(),
|
|
text: inputValue,
|
|
completed: false
|
|
};
|
|
|
|
setTasks([...tasks, newTask]);
|
|
setInputValue('');
|
|
};
|
|
|
|
const toggleTask = (id) => {
|
|
setTasks(tasks.map(task =>
|
|
task.id === id ? { ...task, completed: !task.completed } : task
|
|
));
|
|
};
|
|
|
|
const deleteTask = (id) => {
|
|
setTasks(tasks.filter(task => task.id !== id));
|
|
};
|
|
|
|
const clearCompleted = () => {
|
|
setTasks(tasks.filter(task => !task.completed));
|
|
};
|
|
|
|
return (
|
|
<div style={{
|
|
fontFamily: 'Segoe UI, Roboto, Helvetica, Arial, sans-serif',
|
|
backgroundColor: '#f4f7f6',
|
|
minHeight: '100vh',
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
padding: '40px 20px'
|
|
}}>
|
|
<div style={{
|
|
width: '100%',
|
|
maxWidth: '500px',
|
|
backgroundColor: 'white',
|
|
borderRadius: '12px',
|
|
boxShadow: '0 10px 25px rgba(0,0,0,0.05)',
|
|
padding: '30px'
|
|
}}>
|
|
<h1 style={{ color: '#2c3e50', marginBottom: '25px', textAlign: 'center', fontSize: '24px' }}>
|
|
Menedżer Projektu
|
|
</h1>
|
|
|
|
<form onSubmit={handleAddTask} style={{ display: 'flex', gap: '10px', marginBottom: '30px' }}>
|
|
<input
|
|
type="text"
|
|
value={inputValue}
|
|
onChange={(e) => setInputValue(e.target.value)}
|
|
placeholder="Co należy zrobić?"
|
|
style={{
|
|
flex: 1,
|
|
padding: '12px 15px',
|
|
borderRadius: '8px',
|
|
border: '1px solid #dfe6e9',
|
|
fontSize: '16px',
|
|
outline: 'none'
|
|
}}
|
|
/>
|
|
<button
|
|
type="submit"
|
|
style={{
|
|
padding: '10px 20px',
|
|
backgroundColor: '#3498db',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '8px',
|
|
cursor: 'pointer',
|
|
fontWeight: '600',
|
|
transition: 'background 0.2s'
|
|
}}
|
|
onMouseOver={(e) => e.target.style.backgroundColor = '#2980b9'}
|
|
onMouseOut={(e) => e.target.style.backgroundColor = '#3498db'}
|
|
>
|
|
Dodaj
|
|
</button>
|
|
</form>
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
|
{tasks.length === 0 ? (
|
|
<p style={{ textAlign: 'center', color: '#b2bec3' }}>Brak zadań do wyświetlenia.</p>
|
|
) : (
|
|
tasks.map(task => (
|
|
<div
|
|
key={task.id}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
padding: '12px 15px',
|
|
backgroundColor: task.completed ? '#f9f9f9' : 'white',
|
|
border: '1px solid #f1f2f6',
|
|
borderRadius: '8px',
|
|
transition: 'transform 0.1s'
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
|
<input
|
|
type="checkbox"
|
|
checked={task.completed}
|
|
onChange={() => toggleTask(task.id)}
|
|
style={{ width: '18px', height: '18px', cursor: 'pointer' }}
|
|
/>
|
|
<span style={{
|
|
textDecoration: task.completed ? 'line-through' : 'none',
|
|
color: task.completed ? '#b2bec3' : '#2d3436',
|
|
fontSize: '16px'
|
|
}}>
|
|
{task.text}
|
|
</span>
|
|
</div>
|
|
<button
|
|
onClick={() => deleteTask(task.id)}
|
|
style={{
|
|
background: 'none',
|
|
border: 'none',
|
|
color: '#ff7675',
|
|
cursor: 'pointer',
|
|
fontSize: '14px',
|
|
fontWeight: '500'
|
|
}}
|
|
>
|
|
Usuń
|
|
</button>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
|
|
{tasks.length > 0 && (
|
|
<div style={{
|
|
marginTop: '25px',
|
|
paddingTop: '20px',
|
|
borderTop: '1px solid #f1f2f6',
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
color: '#636e72',
|
|
fontSize: '14px'
|
|
}}>
|
|
<span>Pozostało: {tasks.filter(t => !t.completed).length}</span>
|
|
<button
|
|
onClick={clearCompleted}
|
|
style={{
|
|
background: 'none',
|
|
border: 'none',
|
|
color: '#3498db',
|
|
cursor: 'pointer',
|
|
fontSize: '14px'
|
|
}}
|
|
>
|
|
Wyczyść ukończone
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default App; |