559 lines
28 KiB
PHP
559 lines
28 KiB
PHP
<?php
|
||
|
||
spl_autoload_register(function ($class) {
|
||
$prefix = 'App\\';
|
||
$base_dir = __DIR__ . '/../src/';
|
||
$len = strlen($prefix);
|
||
if (strncmp($prefix, $class, $len) !== 0) {
|
||
return;
|
||
}
|
||
$relative_class = substr($class, $len);
|
||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||
if (file_exists($file)) {
|
||
require $file;
|
||
}
|
||
});
|
||
|
||
use App\Database;
|
||
use App\Album;
|
||
use App\Photo;
|
||
use App\Quote;
|
||
use App\Milestone;
|
||
|
||
// Handle JSON API Endpoints
|
||
if (isset($_GET['api'])) {
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
$api = $_GET['api'];
|
||
|
||
try {
|
||
switch ($api) {
|
||
case 'photos':
|
||
$albumId = !empty($_GET['album_id']) ? (int)$_GET['album_id'] : null;
|
||
$favOnly = !empty($_GET['favorite_only']);
|
||
$search = !empty($_GET['search']) ? trim($_GET['search']) : null;
|
||
echo json_encode(['success' => true, 'data' => Photo::all($albumId, $favOnly, $search)]);
|
||
exit;
|
||
|
||
case 'albums':
|
||
echo json_encode(['success' => true, 'data' => Album::all()]);
|
||
exit;
|
||
|
||
case 'quotes':
|
||
echo json_encode(['success' => true, 'data' => Quote::all()]);
|
||
exit;
|
||
|
||
case 'milestones':
|
||
echo json_encode(['success' => true, 'data' => Milestone::all()]);
|
||
exit;
|
||
|
||
case 'stats':
|
||
echo json_encode(['success' => true, 'data' => Photo::getStats()]);
|
||
exit;
|
||
|
||
case 'like_photo':
|
||
$id = (int)($_GET['id'] ?? 0);
|
||
$likes = Photo::incrementLike($id);
|
||
echo json_encode(['success' => true, 'likes' => $likes]);
|
||
exit;
|
||
|
||
case 'toggle_fav':
|
||
$id = (int)($_GET['id'] ?? 0);
|
||
Photo::toggleFavorite($id);
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
|
||
case 'delete_photo':
|
||
$id = (int)($_GET['id'] ?? 0);
|
||
Photo::delete($id);
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
|
||
case 'delete_album':
|
||
$id = (int)($_GET['id'] ?? 0);
|
||
Album::delete($id);
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
|
||
case 'delete_quote':
|
||
$id = (int)($_GET['id'] ?? 0);
|
||
Quote::delete($id);
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
|
||
case 'delete_milestone':
|
||
$id = (int)($_GET['id'] ?? 0);
|
||
Milestone::delete($id);
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
|
||
case 'upload_photo':
|
||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||
throw new Exception('متد نامعتبر است');
|
||
}
|
||
|
||
if (empty($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
|
||
throw new Exception('لطفاً یک فایل تصویر معتبر انتخاب کنید');
|
||
}
|
||
|
||
$file = $_FILES['photo'];
|
||
$allowed = ['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/svg+xml'];
|
||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||
$mime = finfo_file($finfo, $file['tmp_name']);
|
||
finfo_close($finfo);
|
||
|
||
if (!in_array($mime, $allowed)) {
|
||
throw new Exception('فرمت فایل پشتیبانی نمیشود (فقط JPG، PNG، WEBP، GIF)');
|
||
}
|
||
|
||
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||
if (!$ext) $ext = 'jpg';
|
||
$filename = 'photo_' . time() . '_' . bin2hex(random_bytes(4)) . '.' . $ext;
|
||
$target = __DIR__ . '/uploads/' . $filename;
|
||
|
||
if (!move_uploaded_file($file['tmp_name'], $target)) {
|
||
throw new Exception('خطا در انتقال فایل ذخیرهسازی');
|
||
}
|
||
|
||
$albumId = (int)($_POST['album_id'] ?? 1);
|
||
$title = trim($_POST['title'] ?? 'خاطره جدید');
|
||
$caption = trim($_POST['caption'] ?? '');
|
||
$ageTag = trim($_POST['age_tag'] ?? '۳ سالگی');
|
||
$photoDate = $_POST['photo_date'] ?? date('Y-m-d');
|
||
|
||
$photoId = Photo::create($albumId, $title, 'uploads/' . $filename, $caption, $ageTag, $photoDate);
|
||
echo json_encode(['success' => true, 'photo_id' => $photoId]);
|
||
exit;
|
||
|
||
case 'create_album':
|
||
$title = trim($_POST['title'] ?? '');
|
||
if (!$title) throw new Exception('عنوان آلبوم الزامی است');
|
||
$description = trim($_POST['description'] ?? '');
|
||
$icon = trim($_POST['icon'] ?? '🎈');
|
||
$color = trim($_POST['color'] ?? '#3b82f6');
|
||
|
||
$albumId = Album::create($title, $description, $icon, $color);
|
||
echo json_encode(['success' => true, 'album_id' => $albumId]);
|
||
exit;
|
||
|
||
case 'create_quote':
|
||
$quote = trim($_POST['quote'] ?? '');
|
||
if (!$quote) throw new Exception('متن جمله الزامی است');
|
||
$ageTag = trim($_POST['age_tag'] ?? '۳ سالگی');
|
||
$context = trim($_POST['context'] ?? '');
|
||
$saidDate = $_POST['said_date'] ?? date('Y-m-d');
|
||
|
||
$id = Quote::create($quote, $ageTag, $context, $saidDate);
|
||
echo json_encode(['success' => true, 'quote_id' => $id]);
|
||
exit;
|
||
|
||
case 'create_milestone':
|
||
$title = trim($_POST['title'] ?? '');
|
||
if (!$title) throw new Exception('عنوان دستاورد الزامی است');
|
||
$description = trim($_POST['description'] ?? '');
|
||
$ageTag = trim($_POST['age_tag'] ?? '۳ سالگی');
|
||
$icon = trim($_POST['icon'] ?? '🌟');
|
||
$milestoneDate = $_POST['milestone_date'] ?? date('Y-m-d');
|
||
|
||
$id = Milestone::create($title, $description, $ageTag, $icon, $milestoneDate);
|
||
echo json_encode(['success' => true, 'milestone_id' => $id]);
|
||
exit;
|
||
|
||
default:
|
||
echo json_encode(['success' => false, 'error' => 'مسیر یافت نشد']);
|
||
exit;
|
||
}
|
||
} catch (Throwable $e) {
|
||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||
exit;
|
||
}
|
||
}
|
||
|
||
// Initial Data for HTML Render
|
||
$albums = Album::all();
|
||
$stats = Photo::getStats();
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="fa" dir="rtl">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>آلبوم خاطرات حامد کوچولو 🎈 پسر ۳ ساله</title>
|
||
<link rel="stylesheet" href="assets/css/style.css">
|
||
</head>
|
||
<body>
|
||
|
||
<!-- Floating Background Shapes -->
|
||
<div class="floating-shapes">
|
||
<div class="shape">🎈</div>
|
||
<div class="shape">⭐</div>
|
||
<div class="shape">🧸</div>
|
||
<div class="shape">🚗</div>
|
||
<div class="shape">🎨</div>
|
||
</div>
|
||
|
||
<div class="app-container">
|
||
|
||
<!-- Hero Header -->
|
||
<header class="hero-card">
|
||
<div class="child-profile">
|
||
<div class="avatar-badge">👶</div>
|
||
<div class="child-info">
|
||
<h1>
|
||
<span>آلبوم خاطرات حامد کوچولو</span>
|
||
<span>🎈</span>
|
||
</h1>
|
||
<p>گنجینه عکسها، خندههای شیرین، اولین حرفها و لحظات ناب رشد پسر ۳ ساله ما 💖</p>
|
||
<div class="badge-age">
|
||
<span>🎂</span>
|
||
<span>۳ سال و ۲ ماهه (متولد تابستان ۱۴۰۲)</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="quick-stats">
|
||
<div class="stat-box">
|
||
<div class="stat-number" id="statPhotosCount"><?= $stats['photos'] ?></div>
|
||
<div class="stat-label">📸 عکس شیرین</div>
|
||
</div>
|
||
<div class="stat-box">
|
||
<div class="stat-number" id="statAlbumsCount"><?= $stats['albums'] ?></div>
|
||
<div class="stat-label">📂 آلبوم موضوعی</div>
|
||
</div>
|
||
<div class="stat-box">
|
||
<div class="stat-number" id="statQuotesCount"><?= $stats['quotes'] ?></div>
|
||
<div class="stat-label">💬 جمله بامزه</div>
|
||
</div>
|
||
<div class="stat-box">
|
||
<div class="stat-number" id="statMilestonesCount"><?= $stats['milestones'] ?></div>
|
||
<div class="stat-label">🌟 دستاورد رشد</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Navigation & Main Actions -->
|
||
<nav class="action-bar">
|
||
<div class="nav-tabs">
|
||
<button class="tab-btn active" data-tab="gallery" onclick="switchTab('gallery')">
|
||
<span>📸</span>
|
||
<span>گالری عکسها</span>
|
||
</button>
|
||
<button class="tab-btn" data-tab="albums" onclick="switchTab('albums')">
|
||
<span>📂</span>
|
||
<span>آلبومها</span>
|
||
</button>
|
||
<button class="tab-btn" data-tab="quotes" onclick="switchTab('quotes')">
|
||
<span>💬</span>
|
||
<span>حرفهای بامزه</span>
|
||
</button>
|
||
<button class="tab-btn" data-tab="milestones" onclick="switchTab('milestones')">
|
||
<span>🌟</span>
|
||
<span>خط رشد</span>
|
||
</button>
|
||
<button class="tab-btn" data-tab="slideshow" onclick="switchTab('slideshow')">
|
||
<span>🎵</span>
|
||
<span>اسلایدشو موزیکال</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="btn-group-actions">
|
||
<button class="btn btn-primary" onclick="openModal('uploadPhotoModal')">
|
||
<span>➕</span>
|
||
<span>افزودن عکس جدید</span>
|
||
</button>
|
||
<button class="btn btn-accent" onclick="openModal('newAlbumModal')">
|
||
<span>📁</span>
|
||
<span>ایجاد آلبوم</span>
|
||
</button>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- TAB 1: Gallery -->
|
||
<section id="tab-gallery" class="tab-pane">
|
||
<div class="filters-bar">
|
||
<div class="album-filter-scroll">
|
||
<button class="filter-chip active" onclick="filterByAlbum(null, this)">همه عکسها</button>
|
||
<?php foreach ($albums as $alb): ?>
|
||
<button class="filter-chip" onclick="filterByAlbum(<?= $alb['id'] ?>, this)">
|
||
<?= htmlspecialchars($alb['icon'] . ' ' . $alb['title']) ?>
|
||
</button>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 10px; align-items: center; flex-wrap: wrap;">
|
||
<button id="favFilterBtn" class="btn btn-outline" onclick="toggleFavoriteFilter()" style="padding: 6px 14px; font-size: 0.85rem;">
|
||
⭐ فقط برگزیدهها
|
||
</button>
|
||
<div class="search-box">
|
||
<span class="search-icon">🔍</span>
|
||
<input type="text" id="searchInput" placeholder="جستجو در خاطرات و عکسها...">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Photos Grid -->
|
||
<div class="gallery-grid" id="photosGrid">
|
||
<!-- Dynamically loaded via JS -->
|
||
</div>
|
||
</section>
|
||
|
||
<!-- TAB 2: Albums -->
|
||
<section id="tab-albums" class="tab-pane" style="display: none;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<h2 style="font-size: 1.3rem; font-weight: 800; color: #1e293b;">📂 دستهبندی آلبومهای خاطرات</h2>
|
||
<button class="btn btn-primary" onclick="openModal('newAlbumModal')">+ آلبوم جدید</button>
|
||
</div>
|
||
<div class="albums-grid" id="albumsGrid">
|
||
<!-- Dynamically loaded via JS -->
|
||
</div>
|
||
</section>
|
||
|
||
<!-- TAB 3: Quotes -->
|
||
<section id="tab-quotes" class="tab-pane" style="display: none;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<div>
|
||
<h2 style="font-size: 1.3rem; font-weight: 800; color: #1e293b;">💬 دفترچه جملات و حرفهای بامزه</h2>
|
||
<p style="font-size: 0.88rem; color: #64748b; margin-top: 4px;">ثبت تکهکلامها و حرفهای شیرین و خندهدار ۳ سالگی</p>
|
||
</div>
|
||
<button class="btn btn-primary" onclick="openModal('newQuoteModal')">+ ثبت حرف بامزه</button>
|
||
</div>
|
||
<div class="quotes-grid" id="quotesGrid">
|
||
<!-- Dynamically loaded via JS -->
|
||
</div>
|
||
</section>
|
||
|
||
<!-- TAB 4: Milestones -->
|
||
<section id="tab-milestones" class="tab-pane" style="display: none;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<div>
|
||
<h2 style="font-size: 1.3rem; font-weight: 800; color: #1e293b;">🌟 خط زمانی رشد و دستاوردهای ۳ سالگی</h2>
|
||
<p style="font-size: 0.88rem; color: #64748b; margin-top: 4px;">مراحل مهم، مهارتهای جدید و افتخارات کوچولوی دوستداشتنی</p>
|
||
</div>
|
||
<button class="btn btn-primary" onclick="openModal('newMilestoneModal')">+ ثبت دستاورد جدید</button>
|
||
</div>
|
||
<div class="timeline-container" id="milestonesList">
|
||
<!-- Dynamically loaded via JS -->
|
||
</div>
|
||
</section>
|
||
|
||
<!-- TAB 5: Slideshow -->
|
||
<section id="tab-slideshow" class="tab-pane" style="display: none;">
|
||
<div style="text-align: center; margin-bottom: 20px;">
|
||
<h2 style="font-size: 1.4rem; font-weight: 800; color: #1e293b; margin-bottom: 8px;">🎵 اسلایدشو موزیکال خاطرات</h2>
|
||
<button id="musicToggleBtn" class="btn btn-accent" onclick="toggleLullaby()">
|
||
🎵 پخش موزیک آرامشبخش
|
||
</button>
|
||
</div>
|
||
|
||
<div style="background: #0f172a; border-radius: var(--radius-xl); overflow: hidden; padding: 24px; text-align: center; box-shadow: var(--card-shadow); max-width: 900px; margin: 0 auto;">
|
||
<div style="height: 480px; display: flex; align-items: center; justify-content: center; margin-bottom: 16px;">
|
||
<img id="slideshowCurrentImg" src="" style="max-height: 100%; max-width: 100%; object-fit: contain; border-radius: 12px; transition: opacity 0.5s ease;" alt="Slideshow">
|
||
</div>
|
||
<h3 id="slideshowCurrentTitle" style="color: #ffffff; font-size: 1.3rem; font-weight: 800; margin-bottom: 6px;"></h3>
|
||
<p id="slideshowCurrentDesc" style="color: #94a3b8; font-size: 0.95rem;"></p>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<!-- MODAL: Upload Photo -->
|
||
<div class="modal-overlay" id="uploadPhotoModal">
|
||
<div class="modal-card">
|
||
<button class="modal-close-btn" onclick="closeModal('uploadPhotoModal')">✕</button>
|
||
<div class="modal-header">
|
||
<h2>📸 افزودن عکس خاطرهانگیز جدید</h2>
|
||
</div>
|
||
<form id="uploadPhotoForm" onsubmit="submitPhotoUpload(event)">
|
||
<div class="form-group">
|
||
<label>فایل تصویر</label>
|
||
<div class="file-drop-area" id="fileDropArea">
|
||
<div id="dropText">
|
||
<span style="font-size: 2.5rem;">📷</span>
|
||
<p style="font-weight: 700; color: #1e40af; margin-top: 8px;">برای انتخاب یا رها کردن عکس کلیک کنید</p>
|
||
<p style="font-size: 0.8rem; color: #64748b;">(پشتیبانی از JPG, PNG, WEBP, GIF)</p>
|
||
</div>
|
||
<div id="photoPreviewContainer" style="display: none;">
|
||
<img id="photoPreviewImg" src="" style="max-height: 180px; border-radius: 8px;" alt="پیشنمایش">
|
||
<p style="font-size: 0.8rem; color: #059669; font-weight: 700; margin-top: 6px;">تصویر با موفقیت انتخاب شد ✓</p>
|
||
</div>
|
||
<input type="file" id="photoFileInput" name="photo" accept="image/*" style="display: none;" required>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>عنوان عکس یا مناسبت</label>
|
||
<input type="text" name="title" class="form-control" placeholder="مثلاً: بازی با شنهای ساحل" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>آلبوم مربوطه</label>
|
||
<select name="album_id" class="form-control" id="uploadAlbumSelect">
|
||
<?php foreach ($albums as $alb): ?>
|
||
<option value="<?= $alb['id'] ?>"><?= htmlspecialchars($alb['icon'] . ' ' . $alb['title']) ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>توضیحات و خاطره این عکس</label>
|
||
<textarea name="caption" class="form-control" rows="3" placeholder="خاطره، حرف جالبی که زد یا حس و حال اون لحظه..."></textarea>
|
||
</div>
|
||
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
|
||
<div class="form-group">
|
||
<label>برچسب سن کودک</label>
|
||
<input type="text" name="age_tag" class="form-control" value="۳ سالگی" placeholder="مثلاً: ۳ سال و ۲ ماهگی">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>تاریخ ثبت عکس</label>
|
||
<input type="date" name="photo_date" class="form-control" value="<?= date('Y-m-d') ?>">
|
||
</div>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; justify-content: center; margin-top: 10px; padding: 12px;">
|
||
ذخیره در آلبوم 🎈
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MODAL: New Album -->
|
||
<div class="modal-overlay" id="newAlbumModal">
|
||
<div class="modal-card">
|
||
<button class="modal-close-btn" onclick="closeModal('newAlbumModal')">✕</button>
|
||
<div class="modal-header">
|
||
<h2>📁 ایجاد آلبوم جدید</h2>
|
||
</div>
|
||
<form id="newAlbumForm" onsubmit="submitNewAlbum(event)">
|
||
<div class="form-group">
|
||
<label>نام آلبوم</label>
|
||
<input type="text" name="title" class="form-control" placeholder="مثلاً: بازیهای مهدکودک" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>توضیحات مختصر</label>
|
||
<textarea name="description" class="form-control" rows="2" placeholder="توضیح کوتاه درباره عکسهای این آلبوم..."></textarea>
|
||
</div>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
|
||
<div class="form-group">
|
||
<label>آیکون ایموجی</label>
|
||
<input type="text" name="icon" class="form-control" value="🎈" placeholder="🎂, 🎠, 🎨, 🚗...">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>رنگ تم</label>
|
||
<input type="color" name="color" class="form-control" value="#3b82f6" style="height: 44px; padding: 4px;">
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; justify-content: center; margin-top: 10px;">
|
||
ساخت آلبوم ✨
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MODAL: New Quote -->
|
||
<div class="modal-overlay" id="newQuoteModal">
|
||
<div class="modal-card">
|
||
<button class="modal-close-btn" onclick="closeModal('newQuoteModal')">✕</button>
|
||
<div class="modal-header">
|
||
<h2>💬 ثبت جمله و حرف بامزه</h2>
|
||
</div>
|
||
<form id="newQuoteForm" onsubmit="submitNewQuote(event)">
|
||
<div class="form-group">
|
||
<label>جمله یا حرفی که پسر گلمون زد</label>
|
||
<textarea name="quote" class="form-control" rows="3" placeholder="دقیقاً چی گفت؟..." required></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>موقعیت یا شرایطی که گفت</label>
|
||
<input type="text" name="context" class="form-control" placeholder="مثلاً: موقع خوابیدن، وسط غذا خوردن...">
|
||
</div>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
|
||
<div class="form-group">
|
||
<label>سن کودک در زمان گفتن</label>
|
||
<input type="text" name="age_tag" class="form-control" value="۳ سالگی">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>تاریخ</label>
|
||
<input type="date" name="said_date" class="form-control" value="<?= date('Y-m-d') ?>">
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; justify-content: center; margin-top: 10px;">
|
||
ذخیره در دفترچه خاطرات 🧸
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MODAL: New Milestone -->
|
||
<div class="modal-overlay" id="newMilestoneModal">
|
||
<div class="modal-card">
|
||
<button class="modal-close-btn" onclick="closeModal('newMilestoneModal')">✕</button>
|
||
<div class="modal-header">
|
||
<h2>🌟 ثبت دستاورد رشد جدید</h2>
|
||
</div>
|
||
<form id="newMilestoneForm" onsubmit="submitNewMilestone(event)">
|
||
<div class="form-group">
|
||
<label>عنوان دستاورد یا مهارت جدید</label>
|
||
<input type="text" name="title" class="form-control" placeholder="مثلاً: یادگیری پوشیدن کفش به تنهایی" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>توضیحات و جزئیات</label>
|
||
<textarea name="description" class="form-control" rows="2" placeholder="چطور انجام داد و چه عکسالعملی داشت..."></textarea>
|
||
</div>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px;">
|
||
<div class="form-group">
|
||
<label>ایموجی</label>
|
||
<input type="text" name="icon" class="form-control" value="🌟">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>سن</label>
|
||
<input type="text" name="age_tag" class="form-control" value="۳ سالگی">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>تاریخ</label>
|
||
<input type="date" name="milestone_date" class="form-control" value="<?= date('Y-m-d') ?>">
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; justify-content: center; margin-top: 10px;">
|
||
ثبت در خط زمانی 🚀
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MODAL: Lightbox Viewer -->
|
||
<div class="modal-overlay" id="lightboxModal">
|
||
<div class="modal-card lightbox-modal-card">
|
||
<button class="modal-close-btn" style="z-index: 10; background: rgba(255,255,255,0.8);" onclick="closeModal('lightboxModal')">✕</button>
|
||
<div class="lightbox-content">
|
||
<div class="lightbox-img-area">
|
||
<button onclick="prevLightbox()" style="position: absolute; right: 12px; background: rgba(0,0,0,0.5); color: #fff; border: none; font-size: 1.5rem; width: 44px; height: 44px; border-radius: 50%; cursor: pointer; z-index: 5;">❮</button>
|
||
<img id="lightboxImg" src="" alt="بزرگنمایی">
|
||
<button onclick="nextLightbox()" style="position: absolute; left: 12px; background: rgba(0,0,0,0.5); color: #fff; border: none; font-size: 1.5rem; width: 44px; height: 44px; border-radius: 50%; cursor: pointer; z-index: 5;">❯</button>
|
||
</div>
|
||
<div class="lightbox-sidebar">
|
||
<div>
|
||
<span id="lightboxAlbum" class="photo-album-tag" style="font-size: 0.9rem; margin-bottom: 8px;"></span>
|
||
<h2 id="lightboxTitle" style="font-size: 1.3rem; font-weight: 800; margin-bottom: 10px;"></h2>
|
||
<p id="lightboxCaption" style="font-size: 0.92rem; color: #475569; line-height: 1.6;"></p>
|
||
</div>
|
||
|
||
<div style="border-top: 1px solid #e2e8f0; padding-top: 16px; margin-top: 20px;">
|
||
<div style="display: flex; justify-content: space-between; font-size: 0.85rem; color: #64748b; margin-bottom: 14px;">
|
||
<span>🏷️ سن: <strong id="lightboxAge"></strong></span>
|
||
<span>📅 تاریخ: <strong id="lightboxDate"></strong></span>
|
||
<span>❤️ لایک: <strong id="lightboxLikes"></strong></span>
|
||
</div>
|
||
<div style="display: flex; gap: 10px;">
|
||
<a id="lightboxDownloadBtn" href="" download class="btn btn-outline" style="flex: 1; text-align: center; text-decoration: none; justify-content: center;">
|
||
⬇️ دانلود عکس
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="assets/js/app.js"></script>
|
||
</body>
|
||
</html>
|