<?php
/**
* Small reusable UI snippets for admin CRUD pages.
*/
function adminFlashBox(): void
{
$success = flash('success');
$error = flash('error');
if ($success) {
echo '<div class="mb-5 bg-green-50 border border-green-200 text-green-700 text-sm px-4 py-3 rounded-lg"><i class="bi bi-check-circle-fill"></i> ' . e($success) . '</div>';
}
if ($error) {
echo '<div class="mb-5 bg-red-50 border border-red-200 text-red-700 text-sm px-4 py-3 rounded-lg"><i class="bi bi-exclamation-circle-fill"></i> ' . e($error) . '</div>';
}
}
function inputField(string $label, string $name, string $value = '', string $type = 'text', bool $required = false, string $placeholder = ''): void
{
echo '<label class="block mb-4"><span class="block text-sm font-medium text-gray-700 mb-1.5">' . e($label) . '</span>';
echo '<input type="' . e($type) . '" name="' . e($name) . '" value="' . e($value) . '" placeholder="' . e($placeholder) . '" ' . ($required ? 'required' : '') . ' class="w-full px-4 py-2.5 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary text-sm" /></label>';
}
function textareaField(string $label, string $name, string $value = '', int $rows = 4, bool $required = false): void
{
echo '<label class="block mb-4"><span class="block text-sm font-medium text-gray-700 mb-1.5">' . e($label) . '</span>';
echo '<textarea name="' . e($name) . '" rows="' . $rows . '" ' . ($required ? 'required' : '') . ' class="w-full px-4 py-2.5 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary text-sm">' . e($value) . '</textarea></label>';
}
function checkboxField(string $label, string $name, bool $checked = false): void
{
echo '<label class="flex items-center gap-2 mb-4 text-sm font-medium text-gray-700">';
echo '<input type="checkbox" name="' . e($name) . '" value="1" ' . ($checked ? 'checked' : '') . ' class="rounded border-gray-300 text-primary focus:ring-primary" /> ' . e($label) . '</label>';
}
function numberField(string $label, string $name, $value = 0): void
{
echo '<label class="block mb-4"><span class="block text-sm font-medium text-gray-700 mb-1.5">' . e($label) . '</span>';
echo '<input type="number" name="' . e($name) . '" value="' . e((string) $value) . '" class="w-full px-4 py-2.5 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary text-sm" /></label>';
}
/** Handle a simple file upload for a $_FILES[$fieldName], returns relative path or null. */
function handleUpload(string $fieldName, string $subfolder): ?string
{
if (empty($_FILES[$fieldName]['name']) || $_FILES[$fieldName]['error'] !== UPLOAD_ERR_OK) {
return null;
}
$allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf', 'zip', 'exe', 'rar'];
$ext = strtolower(pathinfo($_FILES[$fieldName]['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowed, true)) {
return null;
}
$safeName = bin2hex(random_bytes(8)) . '.' . $ext;
$destDir = __DIR__ . '/../../uploads/' . $subfolder;
if (!is_dir($destDir)) {
mkdir($destDir, 0755, true);
}
$destPath = $destDir . '/' . $safeName;
if (move_uploaded_file($_FILES[$fieldName]['tmp_name'], $destPath)) {
return 'uploads/' . $subfolder . '/' . $safeName;
}
return null;
}