Skip to content

Commit 845077f

Browse files
authored
Revise title and enhance layout for time page
Modified the title and improved layout for better user experience.
1 parent 30f831e commit 845077f

1 file changed

Lines changed: 136 additions & 124 deletions

File tree

time/index.html

Lines changed: 136 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
<script>fetch('https://api.countapi.xyz/hit/rmkr-dev.github.io/time');</script>
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<title>Time Zone Overlay | RMKR Dev</title>
7+
<title>Global Time Sync | RMKR Dev</title>
88

99
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23FFC300' d='M256 0a256 256 0 1 1 0 512A256 256 0 1 1 256 0zM232 120V256c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2V120c0-13.3-10.7-24-24-24s-24 10.7-24 24z'/%3E%3C/svg%3E">
10-
1110
<script src="https://cdn.tailwindcss.com"></script>
1211
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet">
1312
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" />
@@ -18,208 +17,221 @@
1817
--color-accent: #FFC300; --color-text: #F0F4F8;
1918
--color-muted: #A0AEC0; --color-line: #2D3748;
2019
}
21-
body { font-family: 'Inter', sans-serif; background-color: var(--color-bg); color: var(--color-text); overflow-x: hidden; }
22-
.wrap { max-width: 1100px; margin: 0 auto; padding: 2rem; }
20+
body { font-family: 'Inter', sans-serif; background-color: var(--color-bg); color: var(--color-text); }
21+
.wrap { max-width: 1200px; margin: 0 auto; padding: 2rem; }
2322

2423
.timeline-row {
2524
background: var(--color-card);
2625
border: 1px solid var(--color-line);
2726
border-radius: 12px;
28-
padding: 1.25rem;
29-
margin-bottom: 0.75rem;
27+
padding: 1rem 1.5rem;
28+
margin-bottom: 0.5rem;
29+
display: flex;
30+
align-items: center;
31+
gap: 20px;
32+
animation: slideIn 0.3s ease-out;
3033
}
3134

32-
/* The scrollable grid container */
33-
.grid-container {
34-
overflow-x: auto;
35-
padding-bottom: 8px;
36-
scrollbar-width: thin;
37-
scrollbar-color: var(--color-line) transparent;
38-
}
35+
@keyframes slideIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
3936

40-
.hour-grid {
41-
display: grid;
42-
grid-template-columns: repeat(24, minmax(40px, 1fr));
43-
gap: 4px;
44-
margin-top: 10px;
45-
min-width: 960px; /* Ensures cells don't get too squished */
46-
}
37+
.tz-info { width: 240px; flex-shrink: 0; border-right: 1px solid var(--color-line); padding-right: 15px; }
38+
39+
.grid-viewport { flex-grow: 1; overflow-x: auto; scrollbar-width: none; }
40+
.grid-viewport::-webkit-scrollbar { display: none; }
41+
42+
.hour-grid { display: grid; grid-template-columns: repeat(24, 42px); gap: 4px; }
4743

4844
.hour-cell {
49-
height: 45px;
45+
height: 48px;
5046
background: rgba(255, 255, 255, 0.03);
51-
border: 1px solid rgba(255, 255, 255, 0.05);
47+
border: 1px solid rgba(255, 255, 255, 0.08);
5248
border-radius: 6px;
5349
display: flex;
5450
flex-direction: column;
5551
align-items: center;
5652
justify-content: center;
5753
font-size: 0.7rem;
58-
color: var(--color-muted);
5954
cursor: pointer;
6055
transition: all 0.2s;
6156
}
6257

63-
.hour-cell:hover { background: rgba(255, 195, 0, 0.15); border-color: var(--color-accent); }
64-
.hour-cell.active { background: var(--color-accent) !important; color: var(--color-bg) !important; font-weight: 800; border-color: var(--color-accent); transform: scale(1.05); z-index: 2; }
65-
.hour-cell.business { border-bottom: 3px solid #4ade80; }
66-
.hour-cell.night { background: rgba(0, 0, 0, 0.2); }
67-
68-
.ampm { font-size: 0.55rem; opacity: 0.7; }
58+
.hour-cell:hover { border-color: var(--color-accent); background: rgba(255, 195, 0, 0.1); }
59+
.hour-cell.active {
60+
background: var(--color-accent) !important;
61+
color: var(--color-bg) !important;
62+
font-weight: 800;
63+
transform: scale(1.05);
64+
z-index: 10;
65+
}
66+
.hour-cell.work { border-bottom: 3px solid #4ade80; }
67+
.hour-cell.night { opacity: 0.4; background: rgba(0,0,0,0.2); }
6968

70-
select {
69+
input#tz-search {
7170
background: #0C1524; color: white; border: 1px solid var(--color-line);
72-
padding: 8px 12px; border-radius: 6px; font-size: 0.85rem; outline: none;
71+
padding: 12px 18px; border-radius: 10px; width: 350px; outline: none;
72+
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
7373
}
74+
input#tz-search:focus { border-color: var(--color-accent); }
7475

75-
.btn-gold { background: var(--color-accent); color: var(--color-bg); padding: 0.5rem 1.25rem; border-radius: 6px; font-weight: 700; transition: all 0.2s; }
76-
.btn-gold:hover { opacity: 0.9; transform: translateY(-1px); }
76+
.btn-add {
77+
background: var(--color-accent); color: var(--color-bg);
78+
font-weight: 800; padding: 12px 24px; border-radius: 10px;
79+
text-transform: uppercase; font-size: 0.75rem; letter-spacing: 1px;
80+
}
7781
</style>
7882
</head>
7983
<body>
8084

8185
<div class="wrap">
82-
<header class="flex justify-between items-center mb-8 border-b border-[--color-line] pb-4">
86+
<header class="flex justify-between items-center mb-10">
8387
<div>
84-
<h1 class="text-2xl font-bold tracking-tight">Time <span class="text-[--color-accent]">Sync</span> Overlay</h1>
85-
<p class="text-xs text-[--color-muted] mt-1 uppercase tracking-widest">Global Meeting Planner</p>
88+
<h1 class="text-3xl font-black text-white italic">TIME<span class="text-[--color-accent] not-italic">SYNC</span></h1>
89+
<p class="text-[10px] text-[--color-muted] font-bold tracking-[0.2em] mt-1 uppercase">Principal Engineering Toolkit</p>
90+
</div>
91+
<div class="flex gap-4">
92+
<a href="../stats" class="text-[--color-muted] hover:text-[--color-accent] flex items-center gap-2 text-xs font-bold uppercase">
93+
<i class="fa-solid fa-chart-simple"></i> Stats
94+
</a>
95+
<a href="../" class="bg-[--color-card] w-10 h-10 flex items-center justify-center rounded-xl border border-[--color-line] hover:border-[--color-accent] transition">
96+
<i class="fa-solid fa-house-user"></i>
97+
</a>
8698
</div>
87-
<a href="../" class="text-sm font-bold text-[--color-accent] border border-[--color-accent] px-3 py-1 rounded hover:bg-[--color-accent] hover:text-[--color-bg] transition-all"><i class="fa-solid fa-house mr-1"></i> Hub</a>
8899
</header>
89100

90-
<div class="flex flex-wrap gap-4 mb-6 items-center bg-[#18233C] p-5 rounded-2xl border border-[--color-line]">
91-
<div class="flex flex-col">
92-
<label class="text-[10px] uppercase font-bold text-[--color-muted] mb-2 ml-1">Add Location</label>
93-
<div class="flex gap-2">
94-
<select id="tz-selector" class="w-64">
95-
<option value="UTC">UTC (Universal Time)</option>
96-
<option value="Asia/Kolkata">India (IST)</option>
97-
<option value="America/New_York">New York (EST/EDT)</option>
98-
<option value="Europe/London">London (GMT/BST)</option>
99-
<option value="Asia/Singapore">Singapore (SGT)</option>
100-
<option value="America/Los_Angeles">Pacific Time (PST/PDT)</option>
101-
<option value="Europe/Berlin">Berlin (CET/CEST)</option>
102-
<option value="Australia/Sydney">Sydney (AEST/AEDT)</option>
103-
<option value="Asia/Dubai">Dubai (GST)</option>
104-
<option value="Asia/Tokyo">Tokyo (JST)</option>
105-
</select>
106-
<button onclick="addTimezone()" class="btn-gold">Add</button>
101+
<div class="bg-[--color-card] p-6 rounded-2xl mb-8 border border-[--color-line] flex flex-wrap gap-6 items-center">
102+
<div class="flex flex-col gap-2">
103+
<span class="text-[10px] font-black text-[--color-muted] uppercase tracking-widest ml-1">Global Database Search</span>
104+
<div class="flex gap-3">
105+
<input type="text" id="tz-search" list="all-timezones" placeholder="Type city or country (e.g. London, UTC, IST)...">
106+
<datalist id="all-timezones"></datalist>
107+
<button onclick="addZone()" class="btn-add hover:brightness-110 active:scale-95 transition">Add Zone</button>
107108
</div>
108109
</div>
109110

110-
<div class="ml-auto text-right bg-[#0C1524] px-4 py-2 rounded-lg border border-[--color-line]">
111-
<p class="text-[9px] uppercase font-bold text-[--color-muted]">Your System Time</p>
112-
<p id="local-clock" class="text-lg font-mono text-[--color-accent] font-bold">00:00:00</p>
111+
<div class="ml-auto flex items-center gap-8">
112+
<div class="text-right border-r border-[--color-line] pr-8">
113+
<p class="text-[10px] uppercase text-[--color-muted] font-bold mb-1">Internal Reference</p>
114+
<p id="utc-clock" class="font-mono text-xl text-white font-black">00:00 <span class="text-[--color-accent] text-xs">UTC</span></p>
115+
</div>
116+
<button onclick="resetToNow()" class="text-[10px] font-black text-[--color-accent] border-2 border-[--color-accent] px-4 py-2 rounded-lg hover:bg-[--color-accent] hover:text-[--color-bg] transition-all">
117+
SYNC TO NOW
118+
</button>
113119
</div>
114120
</div>
115121

116-
<div id="timelines-root"></div>
122+
<div id="timeline-container" class="space-y-3">
123+
</div>
117124

118-
<footer class="mt-8 text-center text-[10px] text-[--color-muted] uppercase tracking-widest opacity-50">
119-
WorldTimeBuddy Logic — DST Inclusive — Client-Side Only
120-
</footer>
125+
<div class="mt-8 p-4 bg-blue-900/10 border border-blue-900/30 rounded-xl flex items-center gap-4">
126+
<i class="fa-solid fa-circle-info text-blue-400"></i>
127+
<p class="text-xs text-blue-200/70"><b>Pro-Tip:</b> Click any hour cell to align the timeline. Green underlines indicate 9 AM - 5 PM business hours for that specific region.</p>
128+
</div>
121129
</div>
122130

123131
<script>
124-
// Configuration
125-
// We use a "Global Reference Hour" in UTC (0-23) to sync everything
126-
let globalRefUtcHour = new Date().getUTCHours();
127-
let timezones = [];
128-
129-
// Initialize with Local and UTC
132+
// Initial state: Only show the user's current local timezone
133+
let activeUtcIndex = new Date().getUTCHours();
130134
const localTZ = Intl.DateTimeFormat().resolvedOptions().timeZone;
131-
timezones.push(localTZ);
132-
if (localTZ !== 'UTC') timezones.push('UTC');
133-
134-
function updateClocks() {
135+
let selectedZones = [localTZ];
136+
137+
// Populate searchable IANA database
138+
const allZones = Intl.supportedValuesOf('timeZone');
139+
const datalist = document.getElementById('all-timezones');
140+
allZones.forEach(zone => {
141+
let opt = document.createElement('option');
142+
opt.value = zone;
143+
datalist.appendChild(opt);
144+
});
145+
146+
function updateUTC() {
135147
const now = new Date();
136-
document.getElementById('local-clock').innerText = now.toLocaleTimeString([], { hour12: true });
148+
document.getElementById('utc-clock').innerHTML =
149+
`${now.getUTCHours().toString().padStart(2,'0')}:${now.getUTCMinutes().toString().padStart(2,'0')} <span class="text-[--color-accent] text-xs">UTC</span>`;
137150
}
138151

139-
function addTimezone() {
140-
const select = document.getElementById('tz-selector');
141-
const tz = select.value;
142-
if (!timezones.includes(tz)) {
143-
timezones.push(tz);
152+
function addZone() {
153+
const input = document.getElementById('tz-search');
154+
const val = input.value;
155+
if (allZones.includes(val) && !selectedZones.includes(val)) {
156+
selectedZones.push(val);
144157
render();
158+
input.value = "";
159+
} else if (val === "UTC" && !selectedZones.includes("UTC")) {
160+
selectedZones.push("UTC");
161+
render();
162+
input.value = "";
145163
}
146164
}
147165

148-
function removeTimezone(index) {
149-
timezones.splice(index, 1);
150-
render();
166+
function removeZone(index) {
167+
if (selectedZones.length > 1) {
168+
selectedZones.splice(index, 1);
169+
render();
170+
}
151171
}
152172

153-
function selectHour(utcHour) {
154-
globalRefUtcHour = utcHour;
173+
function resetToNow() {
174+
activeUtcIndex = new Date().getUTCHours();
155175
render();
156176
}
157177

158178
function render() {
159-
const root = document.getElementById('timelines-root');
160-
root.innerHTML = '';
179+
const container = document.getElementById('timeline-container');
180+
container.innerHTML = '';
161181

162-
timezones.forEach((tz, tzIndex) => {
182+
selectedZones.forEach((zone, idx) => {
163183
const row = document.createElement('div');
164-
row.className = 'timeline-row animate-in fade-in duration-500';
184+
row.className = 'timeline-row';
165185

166-
// Get current time info for the header
167186
const now = new Date();
168-
const timeStr = now.toLocaleTimeString('en-US', { timeZone: tz, hour: 'numeric', minute: '2-digit', hour12: true });
169-
const dateStr = now.toLocaleDateString('en-US', { timeZone: tz, weekday: 'short', month: 'short', day: 'numeric' });
187+
const timeInZone = now.toLocaleTimeString('en-US', { timeZone: zone, hour: '2-digit', minute: '2-digit', hour12: true });
188+
const offsetName = new Intl.DateTimeFormat('en-US', {timeZone: zone, timeZoneName:'short'}).formatToParts(now).find(p => p.type === 'timeZoneName').value;
170189

171190
row.innerHTML = `
172-
<div class="flex justify-between items-end mb-3">
173-
<div class="flex items-baseline gap-2">
174-
<span class="font-bold text-lg text-[--color-accent] leading-none">${tz.split('/').pop().replace('_', ' ')}</span>
175-
<span class="text-[10px] font-mono text-[--color-muted] uppercase opacity-60">${tz}</span>
191+
<div class="tz-info">
192+
<div class="flex justify-between items-center mb-1">
193+
<span class="font-black text-white text-sm tracking-tight">${zone.split('/').pop().replace('_', ' ')}</span>
194+
<span class="text-[11px] font-mono text-[--color-accent] font-bold">${timeInZone}</span>
176195
</div>
177-
<div class="text-right">
178-
<span class="text-xs font-bold text-white block">${timeStr}</span>
179-
<span class="text-[9px] text-[--color-muted] uppercase font-medium">${dateStr}</span>
196+
<div class="flex justify-between items-center">
197+
<span class="text-[9px] text-[--color-muted] font-bold uppercase tracking-tighter">${offsetName}</span>
198+
${idx !== 0 ? `<button onclick="removeZone(${idx})" class="text-[9px] font-black text-red-400/50 hover:text-red-400 uppercase tracking-widest">Delete</button>` : `<span class="text-[9px] text-blue-400 font-black uppercase tracking-widest">Local</span>`}
180199
</div>
181-
${tzIndex > 0 ? `<button onclick="removeTimezone(${tzIndex})" class="ml-4 text-[--color-line] hover:text-red-400 transition-colors"><i class="fa-solid fa-circle-minus"></i></button>` : ''}
182200
</div>
183-
<div class="grid-container">
184-
<div class="hour-grid" id="grid-${tzIndex}"></div>
201+
<div class="grid-viewport">
202+
<div class="hour-grid"></div>
185203
</div>
186204
`;
187-
root.appendChild(row);
188205

189-
const grid = document.getElementById(`grid-${tzIndex}`);
206+
const grid = row.querySelector('.hour-grid');
190207

191-
// Logic: We always render 24 blocks.
192-
// The "spine" is UTC. We calculate what hour in THIS timezone corresponds to UTC 0 to 23.
193-
for (let utcHour = 0; utcHour < 24; utcHour++) {
194-
// Create a date object set to Today at utcHour:00 UTC
195-
const refDate = new Date();
196-
refDate.setUTCHours(utcHour, 0, 0, 0);
197-
198-
// Convert that specific UTC moment to the target timezone's hour
199-
const tzHourStr = refDate.toLocaleTimeString('en-US', { timeZone: tz, hour: 'numeric', hour12: false });
200-
const tzHour = parseInt(tzHourStr);
201-
const isAMPM = refDate.toLocaleTimeString('en-US', { timeZone: tz, hour: 'numeric', hour12: true });
202-
208+
// Build 24-hour UTC-aligned spine
209+
for (let i = 0; i < 24; i++) {
203210
const cell = document.createElement('div');
204-
const isBusiness = tzHour >= 9 && tzHour <= 18;
205-
const isNight = tzHour < 6 || tzHour >= 22;
206-
const isActive = utcHour === globalRefUtcHour;
207-
208-
cell.className = `hour-cell ${isBusiness ? 'business' : ''} ${isNight ? 'night' : ''} ${isActive ? 'active' : ''}`;
211+
const d = new Date();
212+
d.setUTCHours(i, 0, 0, 0);
209213

210-
// Format display (e.g., "12 AM" or "5 PM")
211-
const [hPart, ampmPart] = isAMPM.split(' ');
212-
cell.innerHTML = `<span>${hPart}</span><span class="ampm">${ampmPart}</span>`;
214+
const localHour = parseInt(d.toLocaleTimeString('en-US', { timeZone: zone, hour12: false, hour: 'numeric' }));
215+
const ampm = d.toLocaleTimeString('en-US', { timeZone: zone, hour: 'numeric', hour12: true }).split(' ')[1];
216+
217+
const isWork = localHour >= 9 && localHour <= 17;
218+
const isNight = localHour >= 22 || localHour <= 6;
219+
const isActive = i === activeUtcIndex;
220+
221+
cell.className = `hour-cell ${isWork ? 'work' : ''} ${isNight ? 'night' : ''} ${isActive ? 'active' : ''}`;
222+
cell.innerHTML = `<span class="text-xs font-bold">${localHour % 12 || 12}</span><span class="text-[7px] font-black uppercase opacity-60">${ampm}</span>`;
213223

214-
cell.onclick = () => selectHour(utcHour);
224+
cell.onclick = () => { activeUtcIndex = i; render(); };
215225
grid.appendChild(cell);
216226
}
227+
container.appendChild(row);
217228
});
218229
}
219230

220-
setInterval(updateClocks, 1000);
231+
setInterval(updateUTC, 1000);
221232
render();
222-
updateClocks();
233+
updateUTC();
223234
</script>
235+
224236
</body>
225237
</html>

0 commit comments

Comments
 (0)