diff --git a/app/public/assets/css/base.css b/app/public/assets/css/base.css new file mode 100644 index 0000000..c0833e2 --- /dev/null +++ b/app/public/assets/css/base.css @@ -0,0 +1,62 @@ +:root { + --bg: #0f172a; + --panel: #111827; + --panel-2: #1f2937; + --panel-3: #273244; + --border: #334155; + --text: #f8fafc; + --muted: #94a3b8; + --accent: #3b82f6; + --accent-soft: rgba(59, 130, 246, 0.16); + --success: #22c55e; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + background: var(--bg); + color: var(--text); +} + +button { + background: var(--accent); + color: white; + border: 0; + border-radius: 10px; + padding: 10px 16px; + font-weight: 800; + cursor: pointer; +} + +.empty, +.notice { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 16px; + padding: 18px; +} + +.notice { + border-color: #15803d; + background: rgba(34, 197, 94, 0.12); + color: #dcfce7; + margin-bottom: 18px; +} + +.category { + display: inline-block; + margin-top: 10px; + padding: 4px 9px; + border-radius: 999px; + background: var(--panel-3); + color: #dbeafe; + font-size: 0.8rem; +} + +.favorite-star { + color: #facc15; +} diff --git a/app/public/assets/css/channels.css b/app/public/assets/css/channels.css new file mode 100644 index 0000000..e69de29 diff --git a/app/public/assets/css/day.css b/app/public/assets/css/day.css new file mode 100644 index 0000000..5e44979 --- /dev/null +++ b/app/public/assets/css/day.css @@ -0,0 +1,146 @@ +.page-heading { + margin-bottom: 22px; +} + +.page-heading h2 { + margin: 0; + font-size: 1.8rem; +} + +.page-heading p { + color: var(--muted); + margin: 6px 0 0; +} + +.day-toolbar { + display: flex; + justify-content: space-between; + gap: 16px; + align-items: center; + margin-bottom: 22px; + flex-wrap: wrap; +} + +.day-nav { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +.button-link { + display: inline-flex; + align-items: center; + justify-content: center; + background: var(--panel-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: 10px; + padding: 10px 14px; + text-decoration: none; + font-weight: 800; +} + +.button-link:hover { + background: var(--accent-soft); +} + +.day-filter { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +.day-filter input, +.day-filter select { + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 10px; + padding: 10px 12px; +} + +.day-list { + display: grid; + gap: 20px; +} + +.day-channel { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 18px; + overflow: hidden; +} + +.day-channel-header { + background: var(--panel-2); + padding: 15px 18px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.channel-number { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 34px; + height: 26px; + margin-right: 10px; + border-radius: 999px; + background: var(--panel-3); + color: #dbeafe; + font-size: 0.85rem; + font-weight: 800; +} + +.day-programme { + display: grid; + grid-template-columns: 92px 1fr; + gap: 16px; + padding: 16px 18px; + border-top: 1px solid var(--border); +} + +.day-programme.is-current { + background: rgba(34, 197, 94, 0.12); + border-left: 5px solid var(--success); +} + +.day-programme.is-past { + opacity: 0.55; +} + +.day-time { + color: var(--muted); + font-weight: 800; + display: flex; + flex-direction: column; + gap: 4px; +} + +.day-programme-body h3 { + margin: 0; + font-size: 1.08rem; +} + +.day-programme-body p { + color: #cbd5e1; + margin: 10px 0 0; + line-height: 1.45; +} + +@media (max-width: 700px) { + .day-programme { + grid-template-columns: 1fr; + gap: 8px; + } + + .day-time { + flex-direction: row; + } + + .day-time span:first-child::after { + content: "–"; + margin-left: 8px; + } +} diff --git a/app/public/assets/css/layout.css b/app/public/assets/css/layout.css new file mode 100644 index 0000000..5a1116b --- /dev/null +++ b/app/public/assets/css/layout.css @@ -0,0 +1,63 @@ +.app-shell { + min-height: 100vh; + display: grid; + grid-template-columns: 230px 1fr; +} + +.app-main { + min-width: 0; +} + +.app-header { + height: 82px; + background: var(--panel); + border-bottom: 1px solid var(--border); + padding: 16px 28px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; +} + +.brand-title { + font-size: 1.45rem; + font-weight: 800; +} + +.brand-subtitle { + color: var(--muted); + font-size: 0.85rem; + margin-top: 2px; +} + +.search-box input { + width: min(360px, 40vw); + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 999px; + padding: 10px 16px; +} + +.content { + padding: 32px; + max-width: 1280px; +} + +@media (max-width: 900px) { + .app-shell { + grid-template-columns: 1fr; + } + + .content { + padding: 20px; + } + + .app-header { + padding: 14px 20px; + } + + .search-box input { + width: 160px; + } +} diff --git a/app/public/assets/css/main.css b/app/public/assets/css/main.css index e386498..017828e 100644 --- a/app/public/assets/css/main.css +++ b/app/public/assets/css/main.css @@ -1,886 +1,9 @@ -:root { - --bg: #0f172a; - --panel: #111827; - --panel-2: #1f2937; - --panel-3: #273244; - --border: #334155; - --text: #f8fafc; - --muted: #94a3b8; - --accent: #3b82f6; - --accent-soft: rgba(59, 130, 246, 0.16); - --success: #22c55e; -} - -* { - box-sizing: border-box; -} - -body { - margin: 0; - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - background: var(--bg); - color: var(--text); -} - -.app-shell { - min-height: 100vh; - display: grid; - grid-template-columns: 230px 1fr; -} - -.sidebar { - background: #0b1120; - border-right: 1px solid var(--border); - padding: 24px 16px; -} - -.sidebar-nav { - display: flex; - flex-direction: column; - gap: 8px; -} - -.sidebar-nav a { - color: var(--muted); - text-decoration: none; - padding: 12px 14px; - border-radius: 12px; - font-weight: 600; -} - -.sidebar-nav a:hover, -.sidebar-nav a.active { - color: var(--text); - background: var(--accent-soft); -} - -.app-main { - min-width: 0; -} - -.app-header { - height: 82px; - background: var(--panel); - border-bottom: 1px solid var(--border); - padding: 16px 28px; - display: flex; - align-items: center; - justify-content: space-between; - gap: 24px; -} - -.brand-title { - font-size: 1.45rem; - font-weight: 800; -} - -.brand-subtitle { - color: var(--muted); - font-size: 0.85rem; - margin-top: 2px; -} - -.search-box input { - width: min(360px, 40vw); - background: #020617; - color: var(--text); - border: 1px solid var(--border); - border-radius: 999px; - padding: 10px 16px; -} - -.content { - padding: 32px; - max-width: 1280px; -} - -.channel { - margin-bottom: 24px; - background: var(--panel); - border: 1px solid var(--border); - border-radius: 18px; - overflow: hidden; -} - -.channel-header { - padding: 16px 20px; - background: var(--panel-2); - font-size: 1.2rem; - font-weight: 800; -} - -.programme { - padding: 16px 20px; - border-top: 1px solid var(--border); -} - -.programme-time { - color: var(--muted); - font-size: 0.95rem; - margin-bottom: 5px; -} - -.programme-title { - font-size: 1.1rem; - font-weight: 800; -} - -.programme-desc { - color: #cbd5e1; - margin-top: 7px; -} - -.category { - display: inline-block; - margin-top: 10px; - padding: 4px 9px; - border-radius: 999px; - background: var(--panel-3); - color: #dbeafe; - font-size: 0.8rem; -} - -.empty, -.notice { - background: var(--panel); - border: 1px solid var(--border); - border-radius: 16px; - padding: 18px; -} - -.notice { - border-color: #15803d; - background: rgba(34, 197, 94, 0.12); - color: #dcfce7; - margin-bottom: 18px; -} - -button { - background: var(--accent); - color: white; - border: 0; - border-radius: 10px; - padding: 10px 16px; - font-weight: 800; - cursor: pointer; -} - -.settings-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 18px; -} - -.settings-header h2 { - margin: 0; -} - -.channels-table { - width: 100%; - border-collapse: collapse; - background: var(--panel); - border: 1px solid var(--border); - border-radius: 16px; - overflow: hidden; -} - -.channels-table th, -.channels-table td { - padding: 12px; - border-bottom: 1px solid var(--border); - text-align: left; -} - -.channels-table th { - background: var(--panel-2); - color: #cbd5e1; -} - -.channels-table input[type="text"], -.channels-table input[type="number"] { - background: #020617; - color: var(--text); - border: 1px solid var(--border); - border-radius: 8px; - padding: 7px 9px; -} - -.number-input { - width: 70px; -} - -.channel-id { - color: var(--muted); - font-size: 0.8rem; - margin-top: 3px; -} - -@media (max-width: 900px) { - .app-shell { - grid-template-columns: 1fr; - } - - .sidebar { - border-right: 0; - border-bottom: 1px solid var(--border); - } - - .sidebar-nav { - flex-direction: row; - overflow-x: auto; - } - - .content { - padding: 20px; - } - - .app-header { - padding: 14px 20px; - } - - .search-box input { - width: 160px; - } -} - -.settings-subtitle { - color: var(--muted); - margin: 6px 0 0; -} - -.channel-settings-list { - display: grid; - gap: 14px; -} - -.channel-settings-card { - background: var(--panel); - border: 1px solid var(--border); - border-radius: 18px; - padding: 18px; - display: grid; - grid-template-columns: 1fr auto; - gap: 20px; - align-items: center; -} - -.channel-settings-title { - font-size: 1.1rem; - font-weight: 800; -} - -.switch-row { - display: flex; - align-items: center; - gap: 12px; -} - -.channel-settings-fields { - display: flex; - align-items: end; - gap: 14px; - flex-wrap: wrap; -} - -.channel-settings-fields label { - color: var(--muted); - font-size: 0.82rem; - font-weight: 700; -} - -.channel-settings-fields input[type="text"], -.channel-settings-fields input[type="number"] { - display: block; - margin-top: 5px; - background: #020617; - color: var(--text); - border: 1px solid var(--border); - border-radius: 9px; - padding: 8px 10px; -} - -.favorite-toggle { - color: var(--text) !important; - background: var(--panel-2); - border: 1px solid var(--border); - border-radius: 999px; - padding: 9px 12px; - cursor: pointer; -} - -@media (max-width: 900px) { - .channel-settings-card { - grid-template-columns: 1fr; - } -} - -.page-heading { - margin-bottom: 22px; -} - -.page-heading h2 { - margin: 0; - font-size: 1.8rem; -} - -.page-heading p { - margin: 6px 0 0; - color: var(--muted); -} - -.now-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 18px; -} - -.now-card { - background: linear-gradient(180deg, var(--panel-2), var(--panel)); - border: 1px solid var(--border); - border-radius: 20px; - padding: 20px; -} - -.now-channel { - display: flex; - justify-content: space-between; - color: var(--muted); - font-weight: 800; - margin-bottom: 12px; -} - -.now-card h3 { - margin: 0; - font-size: 1.25rem; -} - -.now-subtitle { - color: #cbd5e1; - margin-top: 6px; -} - -.progress-wrap { - margin-top: 18px; -} - -.progress-meta { - display: flex; - justify-content: space-between; - color: var(--muted); - font-size: 0.85rem; - margin-bottom: 7px; -} - -.progress-bar { - height: 10px; - background: #020617; - border-radius: 999px; - overflow: hidden; - border: 1px solid var(--border); -} - -.progress-fill { - height: 100%; - background: var(--accent); - border-radius: 999px; -} - -.remaining { - color: var(--muted); - font-size: 0.85rem; - margin-top: 8px; -} - -.now-desc { - color: #cbd5e1; - margin: 16px 0 0; - line-height: 1.45; -} - -.favorite-star { - color: #facc15; -} - -.page-heading { - margin-bottom: 22px; -} - -.page-heading h2 { - margin: 0; - font-size: 1.8rem; -} - -.page-heading p { - color: var(--muted); - margin: 6px 0 0; -} - -.day-toolbar { - display: flex; - justify-content: space-between; - gap: 16px; - align-items: center; - margin-bottom: 22px; - flex-wrap: wrap; -} - -.day-nav { - display: flex; - gap: 10px; - flex-wrap: wrap; -} - -.button-link { - display: inline-flex; - align-items: center; - justify-content: center; - background: var(--panel-2); - color: var(--text); - border: 1px solid var(--border); - border-radius: 10px; - padding: 10px 14px; - text-decoration: none; - font-weight: 800; -} - -.button-link:hover { - background: var(--accent-soft); -} - -.day-filter { - display: flex; - gap: 10px; - flex-wrap: wrap; -} - -.day-filter input, -.day-filter select { - background: #020617; - color: var(--text); - border: 1px solid var(--border); - border-radius: 10px; - padding: 10px 12px; -} - -.day-list { - display: grid; - gap: 20px; -} - -.day-channel { - background: var(--panel); - border: 1px solid var(--border); - border-radius: 18px; - overflow: hidden; -} - -.day-channel-header { - background: var(--panel-2); - padding: 15px 18px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.channel-number { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 34px; - height: 26px; - margin-right: 10px; - border-radius: 999px; - background: var(--panel-3); - color: #dbeafe; - font-size: 0.85rem; - font-weight: 800; -} - -.day-programme { - display: grid; - grid-template-columns: 92px 1fr; - gap: 16px; - padding: 16px 18px; - border-top: 1px solid var(--border); -} - -.day-programme.is-current { - background: rgba(34, 197, 94, 0.12); - border-left: 5px solid var(--success); -} - -.day-programme.is-past { - opacity: 0.55; -} - -.day-time { - color: var(--muted); - font-weight: 800; - display: flex; - flex-direction: column; - gap: 4px; -} - -.day-programme-body h3 { - margin: 0; - font-size: 1.08rem; -} - -.day-programme-body p { - color: #cbd5e1; - margin: 10px 0 0; - line-height: 1.45; -} - -@media (max-width: 700px) { - .day-programme { - grid-template-columns: 1fr; - gap: 8px; - } - - .day-time { - flex-direction: row; - } - - .day-time span:first-child::after { - content: "–"; - margin-left: 8px; - } -} - -.timeline-wrap { - --minute-width: 2px; - margin-bottom: 28px; - overflow-x: auto; - border: 1px solid var(--border); - border-radius: 18px; - background: var(--panel); -} - -.timeline { - min-width: calc(180px + 1440 * var(--minute-width)); -} - -.timeline-header, -.timeline-row { - display: grid; - grid-template-columns: 180px calc(1440 * var(--minute-width)); -} - -.timeline-header { - position: sticky; - top: 0; - z-index: 5; - background: var(--panel-2); - border-bottom: 1px solid var(--border); -} - -.timeline-channel-head, -.timeline-channel { - position: sticky; - left: 0; - z-index: 4; - background: var(--panel-2); - border-right: 1px solid var(--border); -} - -.timeline-channel-head { - padding: 12px 14px; - font-weight: 800; - color: var(--muted); -} - -.timeline-hours { - position: relative; - height: 46px; - background: - repeating-linear-gradient( - to right, - transparent 0, - transparent calc(60 * var(--minute-width) - 1px), - rgba(148, 163, 184, 0.25) calc(60 * var(--minute-width)), - rgba(148, 163, 184, 0.25) calc(60 * var(--minute-width)) - ); -} - -.timeline-hour { - position: absolute; - top: 12px; - transform: translateX(6px); - color: var(--muted); - font-size: 0.8rem; - font-weight: 800; -} - -.timeline-row { - min-height: 72px; - border-bottom: 1px solid var(--border); -} - -.timeline-channel { - display: flex; - align-items: center; - gap: 8px; - padding: 12px 14px; - font-weight: 800; -} - -.timeline-programmes { - position: relative; - min-height: 72px; - background: - repeating-linear-gradient( - to right, - transparent 0, - transparent calc(60 * var(--minute-width) - 1px), - rgba(148, 163, 184, 0.12) calc(60 * var(--minute-width)), - rgba(148, 163, 184, 0.12) calc(60 * var(--minute-width)) - ); -} - -.timeline-programme { - position: absolute; - top: 9px; - left: calc(var(--start) * var(--minute-width)); - width: calc(var(--duration) * var(--minute-width)); - height: 54px; - overflow: hidden; - border-radius: 12px; - padding: 8px 10px; - background: var(--panel-3); - border: 1px solid rgba(148, 163, 184, 0.25); - color: var(--text); -} - -.timeline-programme strong { - display: block; - font-size: 0.85rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.timeline-programme span { - display: block; - margin-top: 3px; - color: var(--muted); - font-size: 0.75rem; -} - -.timeline-programme.is-current { - background: rgba(34, 197, 94, 0.22); - border-color: var(--success); -} - -.timeline-programme.is-past { - opacity: 0.55; -} - -.timeline-now-line { - position: absolute; - top: 0; - bottom: 0; - width: 2px; - background: #ef4444; - z-index: 100; - pointer-events: none; -} - -.timeline-now-line::before { - content: ""; - position: absolute; - left: -5px; - top: -5px; - width: 12px; - height: 12px; - border-radius: 50%; - background: #ef4444; -} - - -.channel-logo { - width: 34px; - height: 24px; - object-fit: contain; - flex: 0 0 auto; - background: rgba(255, 255, 255, 0.08); - border-radius: 6px; - padding: 2px; -} - -.timeline-channel-name { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.timeline-programme { - cursor: pointer; - transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease; -} - -.timeline-programme:hover { - transform: scale(1.015); - box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35); - z-index: 20; -} - -.timeline-channel { - justify-content: flex-start; -} - -.timeline-channel .channel-number { - margin-right: 0; -} - -.programme-modal[hidden] { - display: none; -} - -.programme-modal { - position: fixed; - inset: 0; - z-index: 999; -} - -.programme-modal-backdrop { - position: absolute; - inset: 0; - background: rgba(2, 6, 23, 0.78); - backdrop-filter: blur(3px); -} - -.programme-modal-card { - position: relative; - width: min(620px, calc(100vw - 32px)); - margin: 10vh auto; - background: var(--panel); - border: 1px solid var(--border); - border-radius: 22px; - padding: 28px; - box-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); -} - -.programme-modal-close { - position: absolute; - top: 14px; - right: 14px; - width: 38px; - height: 38px; - padding: 0; - border-radius: 999px; - font-size: 1.5rem; - line-height: 1; -} - -.programme-modal-time { - color: var(--muted); - font-weight: 800; - margin-bottom: 8px; -} - -.programme-modal-card h2 { - margin: 0 46px 8px 0; - font-size: 1.7rem; -} - -.programme-modal-subtitle { - color: #cbd5e1; - font-size: 1.05rem; - margin-bottom: 12px; -} - -.programme-modal-category { - display: inline-block; - margin-bottom: 14px; - padding: 5px 10px; - border-radius: 999px; - background: var(--panel-3); - color: #dbeafe; - font-size: 0.85rem; - font-weight: 700; -} - -.programme-modal-category:empty, -.programme-modal-subtitle:empty { - display: none; -} - -.programme-modal-card p { - color: #dbe4ef; - line-height: 1.55; - margin: 0; -} - -.guide-search { - position: relative; - margin-bottom: 22px; -} - -.guide-search input { - width: 100%; - background: #020617; - color: var(--text); - border: 1px solid var(--border); - border-radius: 14px; - padding: 13px 16px; - font-size: 1rem; -} - -.guide-search-results { - position: absolute; - z-index: 200; - top: calc(100% + 8px); - left: 0; - right: 0; - background: var(--panel); - border: 1px solid var(--border); - border-radius: 16px; - overflow: hidden; - box-shadow: 0 20px 50px rgba(0,0,0,.45); -} - -.guide-search-result { - padding: 13px 16px; - border-bottom: 1px solid var(--border); - cursor: pointer; -} - -.guide-search-result:hover { - background: var(--accent-soft); -} - -.guide-search-result strong { - display: block; -} - -.guide-search-result span { - display: block; - margin-top: 4px; - color: var(--muted); - font-size: .88rem; -} - -.timeline-zoom { - display: flex; - gap: 8px; - flex-wrap: wrap; -} - -.timeline-zoom button { - background: var(--panel-2); - border: 1px solid var(--border); - color: var(--text); - padding: 9px 12px; -} - -.timeline-zoom button.active { - background: var(--accent); - border-color: var(--accent); -} - -.timeline-wrap { - --minute-width: 2px; -} +@import url("./base.css"); +@import url("./layout.css"); +@import url("./sidebar.css"); +@import url("./channels.css"); +@import url("./now.css"); +@import url("./day.css"); +@import url("./timeline.css"); +@import url("./modal.css"); +@import url("./search.css"); diff --git a/app/public/assets/css/main.css.backup b/app/public/assets/css/main.css.backup new file mode 100644 index 0000000..a9f11e3 --- /dev/null +++ b/app/public/assets/css/main.css.backup @@ -0,0 +1,924 @@ +:root { + --bg: #0f172a; + --panel: #111827; + --panel-2: #1f2937; + --panel-3: #273244; + --border: #334155; + --text: #f8fafc; + --muted: #94a3b8; + --accent: #3b82f6; + --accent-soft: rgba(59, 130, 246, 0.16); + --success: #22c55e; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + background: var(--bg); + color: var(--text); +} + +.app-shell { + min-height: 100vh; + display: grid; + grid-template-columns: 230px 1fr; +} + +.sidebar { + background: #0b1120; + border-right: 1px solid var(--border); + padding: 24px 16px; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 8px; +} + +.sidebar-nav a { + color: var(--muted); + text-decoration: none; + padding: 12px 14px; + border-radius: 12px; + font-weight: 600; +} + +.sidebar-nav a:hover, +.sidebar-nav a.active { + color: var(--text); + background: var(--accent-soft); +} + +.app-main { + min-width: 0; +} + +.app-header { + height: 82px; + background: var(--panel); + border-bottom: 1px solid var(--border); + padding: 16px 28px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; +} + +.brand-title { + font-size: 1.45rem; + font-weight: 800; +} + +.brand-subtitle { + color: var(--muted); + font-size: 0.85rem; + margin-top: 2px; +} + +.search-box input { + width: min(360px, 40vw); + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 999px; + padding: 10px 16px; +} + +.content { + padding: 32px; + max-width: 1280px; +} + +.channel { + margin-bottom: 24px; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 18px; + overflow: hidden; +} + +.channel-header { + padding: 16px 20px; + background: var(--panel-2); + font-size: 1.2rem; + font-weight: 800; +} + +.programme { + padding: 16px 20px; + border-top: 1px solid var(--border); +} + +.programme-time { + color: var(--muted); + font-size: 0.95rem; + margin-bottom: 5px; +} + +.programme-title { + font-size: 1.1rem; + font-weight: 800; +} + +.programme-desc { + color: #cbd5e1; + margin-top: 7px; +} + +.category { + display: inline-block; + margin-top: 10px; + padding: 4px 9px; + border-radius: 999px; + background: var(--panel-3); + color: #dbeafe; + font-size: 0.8rem; +} + +.empty, +.notice { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 16px; + padding: 18px; +} + +.notice { + border-color: #15803d; + background: rgba(34, 197, 94, 0.12); + color: #dcfce7; + margin-bottom: 18px; +} + +button { + background: var(--accent); + color: white; + border: 0; + border-radius: 10px; + padding: 10px 16px; + font-weight: 800; + cursor: pointer; +} + +.settings-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 18px; +} + +.settings-header h2 { + margin: 0; +} + +.channels-table { + width: 100%; + border-collapse: collapse; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 16px; + overflow: hidden; +} + +.channels-table th, +.channels-table td { + padding: 12px; + border-bottom: 1px solid var(--border); + text-align: left; +} + +.channels-table th { + background: var(--panel-2); + color: #cbd5e1; +} + +.channels-table input[type="text"], +.channels-table input[type="number"] { + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 8px; + padding: 7px 9px; +} + +.number-input { + width: 70px; +} + +.channel-id { + color: var(--muted); + font-size: 0.8rem; + margin-top: 3px; +} + +@media (max-width: 900px) { + .app-shell { + grid-template-columns: 1fr; + } + + .sidebar { + border-right: 0; + border-bottom: 1px solid var(--border); + } + + .sidebar-nav { + flex-direction: row; + overflow-x: auto; + } + + .content { + padding: 20px; + } + + .app-header { + padding: 14px 20px; + } + + .search-box input { + width: 160px; + } +} + +.settings-subtitle { + color: var(--muted); + margin: 6px 0 0; +} + +.channel-settings-list { + display: grid; + gap: 14px; +} + +.channel-settings-card { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 18px; + padding: 18px; + display: grid; + grid-template-columns: 1fr auto; + gap: 20px; + align-items: center; +} + +.channel-settings-title { + font-size: 1.1rem; + font-weight: 800; +} + +.switch-row { + display: flex; + align-items: center; + gap: 12px; +} + +.channel-settings-fields { + display: flex; + align-items: end; + gap: 14px; + flex-wrap: wrap; +} + +.channel-settings-fields label { + color: var(--muted); + font-size: 0.82rem; + font-weight: 700; +} + +.channel-settings-fields input[type="text"], +.channel-settings-fields input[type="number"] { + display: block; + margin-top: 5px; + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 9px; + padding: 8px 10px; +} + +.favorite-toggle { + color: var(--text) !important; + background: var(--panel-2); + border: 1px solid var(--border); + border-radius: 999px; + padding: 9px 12px; + cursor: pointer; +} + +@media (max-width: 900px) { + .channel-settings-card { + grid-template-columns: 1fr; + } +} + +.page-heading { + margin-bottom: 22px; +} + +.page-heading h2 { + margin: 0; + font-size: 1.8rem; +} + +.page-heading p { + margin: 6px 0 0; + color: var(--muted); +} + +.now-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 18px; +} + +.now-card { + background: linear-gradient(180deg, var(--panel-2), var(--panel)); + border: 1px solid var(--border); + border-radius: 20px; + padding: 20px; +} + +.now-channel { + display: flex; + justify-content: space-between; + color: var(--muted); + font-weight: 800; + margin-bottom: 12px; +} + +.now-card h3 { + margin: 0; + font-size: 1.25rem; +} + +.now-subtitle { + color: #cbd5e1; + margin-top: 6px; +} + +.progress-wrap { + margin-top: 18px; +} + +.progress-meta { + display: flex; + justify-content: space-between; + color: var(--muted); + font-size: 0.85rem; + margin-bottom: 7px; +} + +.progress-bar { + height: 10px; + background: #020617; + border-radius: 999px; + overflow: hidden; + border: 1px solid var(--border); +} + +.progress-fill { + height: 100%; + background: var(--accent); + border-radius: 999px; +} + +.remaining { + color: var(--muted); + font-size: 0.85rem; + margin-top: 8px; +} + +.now-desc { + color: #cbd5e1; + margin: 16px 0 0; + line-height: 1.45; +} + +.favorite-star { + color: #facc15; +} + +.page-heading { + margin-bottom: 22px; +} + +.page-heading h2 { + margin: 0; + font-size: 1.8rem; +} + +.page-heading p { + color: var(--muted); + margin: 6px 0 0; +} + +.day-toolbar { + display: flex; + justify-content: space-between; + gap: 16px; + align-items: center; + margin-bottom: 22px; + flex-wrap: wrap; +} + +.day-nav { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +.button-link { + display: inline-flex; + align-items: center; + justify-content: center; + background: var(--panel-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: 10px; + padding: 10px 14px; + text-decoration: none; + font-weight: 800; +} + +.button-link:hover { + background: var(--accent-soft); +} + +.day-filter { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +.day-filter input, +.day-filter select { + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 10px; + padding: 10px 12px; +} + +.day-list { + display: grid; + gap: 20px; +} + +.day-channel { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 18px; + overflow: hidden; +} + +.day-channel-header { + background: var(--panel-2); + padding: 15px 18px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.channel-number { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 34px; + height: 26px; + margin-right: 10px; + border-radius: 999px; + background: var(--panel-3); + color: #dbeafe; + font-size: 0.85rem; + font-weight: 800; +} + +.day-programme { + display: grid; + grid-template-columns: 92px 1fr; + gap: 16px; + padding: 16px 18px; + border-top: 1px solid var(--border); +} + +.day-programme.is-current { + background: rgba(34, 197, 94, 0.12); + border-left: 5px solid var(--success); +} + +.day-programme.is-past { + opacity: 0.55; +} + +.day-time { + color: var(--muted); + font-weight: 800; + display: flex; + flex-direction: column; + gap: 4px; +} + +.day-programme-body h3 { + margin: 0; + font-size: 1.08rem; +} + +.day-programme-body p { + color: #cbd5e1; + margin: 10px 0 0; + line-height: 1.45; +} + +@media (max-width: 700px) { + .day-programme { + grid-template-columns: 1fr; + gap: 8px; + } + + .day-time { + flex-direction: row; + } + + .day-time span:first-child::after { + content: "–"; + margin-left: 8px; + } +} + +.timeline-wrap { + --minute-width: 2px; + margin-bottom: 28px; + overflow-x: auto; + border: 1px solid var(--border); + border-radius: 18px; + background: var(--panel); + cursor: grab; + user-select: none; +} + +.timeline-wrap.dragging { + cursor: grabbing; +} + +.timeline { + min-width: calc(180px + 1440 * var(--minute-width)); +} + +.timeline-header, +.timeline-row { + display: grid; + grid-template-columns: 180px calc(1440 * var(--minute-width)); +} + +.timeline-header { + position: sticky; + top: 0; + z-index: 5; + background: var(--panel-2); + border-bottom: 1px solid var(--border); +} + +.timeline-channel-head, +.timeline-channel { + position: sticky; + left: 0; + z-index: 4; + background: var(--panel-2); + border-right: 1px solid var(--border); +} + +.timeline-channel-head { + padding: 12px 14px; + font-weight: 800; + color: var(--muted); +} + +.timeline-hours { + position: relative; + height: 46px; + background-image: + repeating-linear-gradient( + to right, + rgba(148, 163, 184, 0.28) 0, + rgba(148, 163, 184, 0.28) 1px, + transparent 1px, + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.16) calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.16) calc(30 * var(--minute-width)), + transparent calc(30 * var(--minute-width)), + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.07) calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.07) calc(15 * var(--minute-width)), + transparent calc(15 * var(--minute-width)), + transparent calc(30 * var(--minute-width)) + ); +} + +.timeline-hour { + position: absolute; + top: 12px; + transform: translateX(6px); + color: var(--muted); + font-size: 0.8rem; + font-weight: 800; +} + +.timeline-row { + min-height: 72px; + border-bottom: 1px solid var(--border); +} + +.timeline-channel { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 14px; + font-weight: 800; +} + +.timeline-programmes { + position: relative; + min-height: 72px; + background-image: + repeating-linear-gradient( + to right, + rgba(148, 163, 184, 0.18) 0, + rgba(148, 163, 184, 0.18) 1px, + transparent 1px, + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.10) calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.10) calc(30 * var(--minute-width)), + transparent calc(30 * var(--minute-width)), + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.045) calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.045) calc(15 * var(--minute-width)), + transparent calc(15 * var(--minute-width)), + transparent calc(30 * var(--minute-width)) + ); +} + +.timeline-programme { + position: absolute; + top: 9px; + left: calc(var(--start) * var(--minute-width)); + width: calc(var(--duration) * var(--minute-width)); + height: 54px; + overflow: hidden; + border-radius: 12px; + padding: 8px 10px; + background: var(--panel-3); + border: 1px solid rgba(148, 163, 184, 0.25); + color: var(--text); +} + +.timeline-programme strong { + display: block; + font-size: 0.85rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.timeline-programme span { + display: block; + margin-top: 3px; + color: var(--muted); + font-size: 0.75rem; +} + +.timeline-programme.is-current { + background: rgba(34, 197, 94, 0.22); + border-color: var(--success); +} + +.timeline-programme.is-past { + opacity: 0.55; +} + +.timeline-now-line { + position: absolute; + top: 0; + bottom: 0; + width: 2px; + background: #ef4444; + z-index: 100; + pointer-events: none; +} + +.timeline-now-line::before { + content: ""; + position: absolute; + left: -5px; + top: -5px; + width: 12px; + height: 12px; + border-radius: 50%; + background: #ef4444; +} + + +.channel-logo { + width: 34px; + height: 24px; + object-fit: contain; + flex: 0 0 auto; + background: rgba(255, 255, 255, 0.08); + border-radius: 6px; + padding: 2px; +} + +.timeline-channel-name { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.timeline-programme { + cursor: pointer; + transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease; +} + +.timeline-programme:hover { + transform: scale(1.015); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35); + z-index: 20; +} + +.timeline-channel { + justify-content: flex-start; +} + +.timeline-channel .channel-number { + margin-right: 0; +} + +.programme-modal[hidden] { + display: none; +} + +.programme-modal { + position: fixed; + inset: 0; + z-index: 999; +} + +.programme-modal-backdrop { + position: absolute; + inset: 0; + background: rgba(2, 6, 23, 0.78); + backdrop-filter: blur(3px); +} + +.programme-modal-card { + position: relative; + width: min(620px, calc(100vw - 32px)); + margin: 10vh auto; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 22px; + padding: 28px; + box-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); +} + +.programme-modal-close { + position: absolute; + top: 14px; + right: 14px; + width: 38px; + height: 38px; + padding: 0; + border-radius: 999px; + font-size: 1.5rem; + line-height: 1; +} + +.programme-modal-time { + color: var(--muted); + font-weight: 800; + margin-bottom: 8px; +} + +.programme-modal-card h2 { + margin: 0 46px 8px 0; + font-size: 1.7rem; +} + +.programme-modal-subtitle { + color: #cbd5e1; + font-size: 1.05rem; + margin-bottom: 12px; +} + +.programme-modal-category { + display: inline-block; + margin-bottom: 14px; + padding: 5px 10px; + border-radius: 999px; + background: var(--panel-3); + color: #dbeafe; + font-size: 0.85rem; + font-weight: 700; +} + +.programme-modal-category:empty, +.programme-modal-subtitle:empty { + display: none; +} + +.programme-modal-card p { + color: #dbe4ef; + line-height: 1.55; + margin: 0; +} + +.guide-search { + position: relative; + margin-bottom: 22px; +} + +.guide-search input { + width: 100%; + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 14px; + padding: 13px 16px; + font-size: 1rem; +} + +.guide-search-results { + position: absolute; + z-index: 200; + top: calc(100% + 8px); + left: 0; + right: 0; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 16px; + overflow: hidden; + box-shadow: 0 20px 50px rgba(0,0,0,.45); +} + +.guide-search-result { + padding: 13px 16px; + border-bottom: 1px solid var(--border); + cursor: pointer; +} + +.guide-search-result:hover { + background: var(--accent-soft); +} + +.guide-search-result strong { + display: block; +} + +.guide-search-result span { + display: block; + margin-top: 4px; + color: var(--muted); + font-size: .88rem; +} + +.timeline-zoom { + display: flex; + gap: 8px; + flex-wrap: wrap; +} + +.timeline-zoom button { + background: var(--panel-2); + border: 1px solid var(--border); + color: var(--text); + padding: 9px 12px; +} + +.timeline-zoom button.active { + background: var(--accent); + border-color: var(--accent); +} diff --git a/app/public/assets/css/modal.css b/app/public/assets/css/modal.css new file mode 100644 index 0000000..439dd72 --- /dev/null +++ b/app/public/assets/css/modal.css @@ -0,0 +1,78 @@ +.programme-modal[hidden] { + display: none; +} + +.programme-modal { + position: fixed; + inset: 0; + z-index: 999; +} + +.programme-modal-backdrop { + position: absolute; + inset: 0; + background: rgba(2, 6, 23, 0.78); + backdrop-filter: blur(3px); +} + +.programme-modal-card { + position: relative; + width: min(620px, calc(100vw - 32px)); + margin: 10vh auto; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 22px; + padding: 28px; + box-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); +} + +.programme-modal-close { + position: absolute; + top: 14px; + right: 14px; + width: 38px; + height: 38px; + padding: 0; + border-radius: 999px; + font-size: 1.5rem; + line-height: 1; +} + +.programme-modal-time { + color: var(--muted); + font-weight: 800; + margin-bottom: 8px; +} + +.programme-modal-card h2 { + margin: 0 46px 8px 0; + font-size: 1.7rem; +} + +.programme-modal-subtitle { + color: #cbd5e1; + font-size: 1.05rem; + margin-bottom: 12px; +} + +.programme-modal-category { + display: inline-block; + margin-bottom: 14px; + padding: 5px 10px; + border-radius: 999px; + background: var(--panel-3); + color: #dbeafe; + font-size: 0.85rem; + font-weight: 700; +} + +.programme-modal-category:empty, +.programme-modal-subtitle:empty { + display: none; +} + +.programme-modal-card p { + color: #dbe4ef; + line-height: 1.55; + margin: 0; +} diff --git a/app/public/assets/css/now.css b/app/public/assets/css/now.css new file mode 100644 index 0000000..e69de29 diff --git a/app/public/assets/css/search.css b/app/public/assets/css/search.css new file mode 100644 index 0000000..4b8fd70 --- /dev/null +++ b/app/public/assets/css/search.css @@ -0,0 +1,48 @@ +.guide-search { + position: relative; + margin-bottom: 22px; +} + +.guide-search input { + width: 100%; + background: #020617; + color: var(--text); + border: 1px solid var(--border); + border-radius: 14px; + padding: 13px 16px; + font-size: 1rem; +} + +.guide-search-results { + position: absolute; + z-index: 200; + top: calc(100% + 8px); + left: 0; + right: 0; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 16px; + overflow: hidden; + box-shadow: 0 20px 50px rgba(0,0,0,.45); +} + +.guide-search-result { + padding: 13px 16px; + border-bottom: 1px solid var(--border); + cursor: pointer; +} + +.guide-search-result:hover { + background: var(--accent-soft); +} + +.guide-search-result strong { + display: block; +} + +.guide-search-result span { + display: block; + margin-top: 4px; + color: var(--muted); + font-size: .88rem; +} diff --git a/app/public/assets/css/sidebar.css b/app/public/assets/css/sidebar.css new file mode 100644 index 0000000..dd569d9 --- /dev/null +++ b/app/public/assets/css/sidebar.css @@ -0,0 +1,37 @@ +.sidebar { + background: #0b1120; + border-right: 1px solid var(--border); + padding: 24px 16px; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 8px; +} + +.sidebar-nav a { + color: var(--muted); + text-decoration: none; + padding: 12px 14px; + border-radius: 12px; + font-weight: 600; +} + +.sidebar-nav a:hover, +.sidebar-nav a.active { + color: var(--text); + background: var(--accent-soft); +} + +@media (max-width: 900px) { + .sidebar { + border-right: 0; + border-bottom: 1px solid var(--border); + } + + .sidebar-nav { + flex-direction: row; + overflow-x: auto; + } +} diff --git a/app/public/assets/css/timeline.css b/app/public/assets/css/timeline.css new file mode 100644 index 0000000..d82d655 --- /dev/null +++ b/app/public/assets/css/timeline.css @@ -0,0 +1,238 @@ +.timeline-wrap { + --minute-width: 2px; + margin-bottom: 28px; + overflow-x: auto; + border: 1px solid var(--border); + border-radius: 18px; + background: var(--panel); + cursor: grab; + user-select: none; +} + +.timeline-wrap.dragging { + cursor: grabbing; +} + +.timeline { + min-width: calc(180px + 1440 * var(--minute-width)); +} + +.timeline-header, +.timeline-row { + display: grid; + grid-template-columns: 180px calc(1440 * var(--minute-width)); +} + +.timeline-header { + position: sticky; + top: 0; + z-index: 5; + background: var(--panel-2); + border-bottom: 1px solid var(--border); +} + +.timeline-channel-head, +.timeline-channel { + position: sticky; + left: 0; + z-index: 4; + background: var(--panel-2); + border-right: 1px solid var(--border); +} + +.timeline-channel-head { + padding: 12px 14px; + font-weight: 800; + color: var(--muted); +} + +.timeline-hours { + position: relative; + height: 46px; + background-image: + repeating-linear-gradient( + to right, + rgba(148, 163, 184, 0.28) 0, + rgba(148, 163, 184, 0.28) 1px, + transparent 1px, + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.16) calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.16) calc(30 * var(--minute-width)), + transparent calc(30 * var(--minute-width)), + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.07) calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.07) calc(15 * var(--minute-width)), + transparent calc(15 * var(--minute-width)), + transparent calc(30 * var(--minute-width)) + ); +} + +.timeline-hour { + position: absolute; + top: 12px; + transform: translateX(6px); + color: var(--muted); + font-size: 0.8rem; + font-weight: 800; +} + +.timeline-row { + min-height: 72px; + border-bottom: 1px solid var(--border); +} + +.timeline-channel { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 8px; + padding: 12px 14px; + font-weight: 800; +} + +.timeline-channel .channel-number { + margin-right: 0; +} + +.timeline-channel-name { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.channel-logo { + width: 34px; + height: 24px; + object-fit: contain; + flex: 0 0 auto; + background: rgba(255, 255, 255, 0.08); + border-radius: 6px; + padding: 2px; +} + +.timeline-programmes { + position: relative; + min-height: 72px; + background-image: + repeating-linear-gradient( + to right, + rgba(148, 163, 184, 0.18) 0, + rgba(148, 163, 184, 0.18) 1px, + transparent 1px, + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.10) calc(30 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.10) calc(30 * var(--minute-width)), + transparent calc(30 * var(--minute-width)), + transparent calc(60 * var(--minute-width)) + ), + repeating-linear-gradient( + to right, + transparent 0, + transparent calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.045) calc(15 * var(--minute-width) - 1px), + rgba(148, 163, 184, 0.045) calc(15 * var(--minute-width)), + transparent calc(15 * var(--minute-width)), + transparent calc(30 * var(--minute-width)) + ); +} + +.timeline-programme { + position: absolute; + top: 9px; + left: calc(var(--start) * var(--minute-width)); + width: calc(var(--duration) * var(--minute-width)); + height: 54px; + overflow: hidden; + border-radius: 12px; + padding: 8px 10px; + background: var(--panel-3); + border: 1px solid rgba(148, 163, 184, 0.25); + color: var(--text); + cursor: pointer; + transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease; +} + +.timeline-programme:hover { + transform: scale(1.015); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35); + z-index: 20; +} + +.timeline-programme strong { + display: block; + font-size: 0.85rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.timeline-programme span { + display: block; + margin-top: 3px; + color: var(--muted); + font-size: 0.75rem; +} + +.timeline-programme.is-current { + background: rgba(34, 197, 94, 0.22); + border-color: var(--success); +} + +.timeline-programme.is-past { + opacity: 0.55; +} + +.timeline-now-line { + position: absolute; + top: 0; + bottom: 0; + width: 2px; + background: #ef4444; + z-index: 100; + pointer-events: none; +} + +.timeline-now-line::before { + content: ""; + position: absolute; + left: -5px; + top: -5px; + width: 12px; + height: 12px; + border-radius: 50%; + background: #ef4444; +} + +.timeline-zoom { + display: flex; + gap: 8px; + flex-wrap: wrap; +} + +.timeline-zoom button { + background: var(--panel-2); + border: 1px solid var(--border); + color: var(--text); + padding: 9px 12px; +} + +.timeline-zoom button.active { + background: var(--accent); + border-color: var(--accent); +} diff --git a/app/public/assets/js/app.js b/app/public/assets/js/app.js index c68f03c..8dd1714 100644 --- a/app/public/assets/js/app.js +++ b/app/public/assets/js/app.js @@ -164,4 +164,52 @@ document.addEventListener("DOMContentLoaded", () => { applyZoom(savedZoom); }); +document.addEventListener("DOMContentLoaded", () => { + + const timeline = document.querySelector(".timeline-wrap"); + + if (!timeline) + return; + + let isDragging = false; + let startX = 0; + let scrollLeft = 0; + + timeline.addEventListener("mousedown", (e) => { + + // nicht wenn auf eine Sendung geklickt wird + if (e.target.closest(".timeline-programme")) + return; + + isDragging = true; + + timeline.classList.add("dragging"); + + startX = e.pageX; + scrollLeft = timeline.scrollLeft; + }); + + document.addEventListener("mouseup", () => { + + isDragging = false; + + timeline.classList.remove("dragging"); + }); + + document.addEventListener("mousemove", (e) => { + + if (!isDragging) + return; + + e.preventDefault(); + + const walk = e.pageX - startX; + + timeline.scrollLeft = scrollLeft - walk; + + }); + +}); + console.log('TVGuide loaded'); + diff --git a/app/public/index.php b/app/public/index.php index 56b785d..53c3c3e 100644 --- a/app/public/index.php +++ b/app/public/index.php @@ -44,7 +44,8 @@ if ($view === 'channels' && $_SERVER['REQUEST_METHOD'] === 'POST') { $currentProgrammes = $xmltv->getCurrentProgrammes($config); -$selectedDate = $_GET['date'] ?? date('Y-m-d'); +$tz = new DateTimeZone($config->get('timezone', 'Europe/Vienna')); +$selectedDate = $_GET['date'] ?? (new DateTime('now', $tz))->format('Y-m-d'); $selectedChannel = $_GET['channel'] ?? null; if ($selectedChannel === '') { @@ -57,12 +58,17 @@ if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $selectedDate)) { $dayProgrammes = $xmltv->getDayProgrammes($config, $selectedDate, $selectedChannel); -$isToday = ($selectedDate === date('Y-m-d')); +$tz = new DateTimeZone($config->get('timezone', 'Europe/Vienna')); +$nowDateTime = new DateTime('now', $tz); + +$isToday = ($selectedDate === $nowDateTime->format('Y-m-d')); $nowMinute = null; if ($isToday) { - $nowMinute = ((int)date('H') * 60) + (int)date('i'); + $nowMinute = + ((int)$nowDateTime->format('H') * 60) + + (int)$nowDateTime->format('i'); } $contentTemplate = match ($view) {