130 lines
3.8 KiB
PHP
130 lines
3.8 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use PHPNative\Framework\Application;
|
|
use PHPNative\Ui\Widget\Button;
|
|
use PHPNative\Ui\Widget\Checkbox;
|
|
use PHPNative\Ui\Widget\Container;
|
|
use PHPNative\Ui\Widget\Label;
|
|
use PHPNative\Ui\Widget\TextInput;
|
|
use PHPNative\Ui\Window;
|
|
|
|
$app = new Application();
|
|
$window = new Window('Todo App', 600, 500);
|
|
|
|
// Main container
|
|
$mainContainer = new Container('flex flex-col p-4 bg-gray-50');
|
|
|
|
// Title
|
|
$title = new Label('My Todo List', 'text-2xl font-bold mb-4 text-gray-800');
|
|
$mainContainer->addComponent($title);
|
|
|
|
// Input section
|
|
$inputContainer = new Container('flex flex-row mb-4');
|
|
|
|
$input = new TextInput(
|
|
placeholder: 'What needs to be done?',
|
|
style: 'flex-1 p-2 border border-gray-300 rounded mr-2',
|
|
);
|
|
|
|
$addButton = new Button('Add', 'bg-blue-500 text-white p-2 rounded-lg hover:bg-blue-600');
|
|
|
|
$inputContainer->addComponent($input);
|
|
$inputContainer->addComponent($addButton);
|
|
$mainContainer->addComponent($inputContainer);
|
|
|
|
// Todo list container
|
|
$todoListContainer = new Container('flex flex-col');
|
|
$mainContainer->addComponent($todoListContainer);
|
|
|
|
// Stats
|
|
$statsLabel = new Label('0 items', 'mt-4 text-gray-600 text-sm h-10');
|
|
$mainContainer->addComponent($statsLabel);
|
|
|
|
// Todos array
|
|
$todos = [];
|
|
|
|
// Function to update stats
|
|
$updateStats = function () use (&$todos, $statsLabel) {
|
|
$total = count($todos);
|
|
$completed = count(array_filter($todos, fn($t) => $t['completed']));
|
|
$statsLabel->setText("{$total} items ({$completed} completed)");
|
|
};
|
|
|
|
// Function to render todos - use a reference so it can be used in closures
|
|
$renderTodos = null;
|
|
$renderTodos = function () use (&$todos, $todoListContainer, $updateStats, &$renderTodos, $window) {
|
|
// Clear existing todos
|
|
$todoListContainer->clearChildren();
|
|
|
|
foreach ($todos as $index => $todo) {
|
|
$todoItem = new Container('flex flex-row items-center p-2 mb-2 bg-white border border-gray-200 rounded h-12');
|
|
|
|
// Checkbox
|
|
$checkbox = new Checkbox(
|
|
label: '',
|
|
checked: $todo['completed'],
|
|
style: 'mr-2 w-6 h-6',
|
|
);
|
|
|
|
$checkbox->setOnChange(function ($checked) use (&$todos, $index, &$renderTodos, $updateStats) {
|
|
$todos[$index]['completed'] = $checked;
|
|
$updateStats();
|
|
});
|
|
|
|
// Text
|
|
$textStyle = $todo['completed'] ? 'flex-1 text-gray-400 line-through' : 'flex-1 text-gray-800';
|
|
$todoText = new Label($todo['text'], $textStyle);
|
|
|
|
// Delete button
|
|
$deleteButton = new Button('Delete', 'bg-red-500 text-white px-2 py-1 rounded text-sm hover:bg-red-600');
|
|
$deleteButton->setOnClick(function () use (&$todos, $index, &$renderTodos, $updateStats) {
|
|
array_splice($todos, $index, 1);
|
|
$renderTodos();
|
|
$updateStats();
|
|
});
|
|
|
|
$todoItem->addComponent($checkbox);
|
|
$todoItem->addComponent($todoText);
|
|
$todoItem->addComponent($deleteButton);
|
|
|
|
$todoListContainer->addComponent($todoItem);
|
|
}
|
|
|
|
$updateStats();
|
|
|
|
// Trigger re-layout after adding new components
|
|
$window->setShouldBeReLayouted(true);
|
|
};
|
|
|
|
// Add button click handler
|
|
$addButton->setOnClick(function () use ($input, &$todos, &$renderTodos) {
|
|
$text = trim($input->getValue());
|
|
|
|
if (!empty($text)) {
|
|
$todos[] = [
|
|
'text' => $text,
|
|
'completed' => false,
|
|
];
|
|
|
|
$input->setValue(''); // Clear input
|
|
$renderTodos();
|
|
}
|
|
});
|
|
|
|
// Handle Enter key in input
|
|
$input->setOnChange(function ($value) {
|
|
// Could add live validation here
|
|
});
|
|
|
|
$window->setRoot($mainContainer);
|
|
$app->addWindow($window);
|
|
|
|
echo "Todo App started!\n";
|
|
echo "- Type in the input field and click 'Add' or press Enter\n";
|
|
echo "- Click checkboxes to mark todos as complete\n";
|
|
echo "- Click 'Delete' to remove a todo\n\n";
|
|
|
|
$app->run();
|