Files
abdus b5aecf4304 feat(web): Add geolocation button, clear location, i18n, and spacing fixes
Add a "use my current location" button next to the search box (shown
only when no location is selected), make clearing the search box reset
selected location, prayer times, and URL coords, rebalance vertical
spacing so the clock isn't flush against the viewport edge, and
translate all UI copy based on browser language.
2026-10-08 21:00:44 +02:00

191 lines
8.3 KiB
HTML

<!doctype html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport'
content='width=device-width, initial-scale=1.0'>
<title>Prayer Times</title>
<script defer
src='main.js'></script>
<script defer
src='alpine.persist@3.x.x.min.js'></script>
<script defer
src='alpine@3.11.1.min.js'></script>
<link rel='preconnect'
href='https://fonts.googleapis.com'>
<link rel='preconnect'
href='https://fonts.gstatic.com'
crossorigin>
<link href='https://fonts.googleapis.com/css2?family=Inter:wght@400..900&family=Noto+Sans+Arabic:wght@400..700&display=swap'
rel='stylesheet'>
<link rel='stylesheet'
href='style.css'>
</head>
<body>
<div x-data='app()'
@hashchange.window='onHash'
class='app'>
<template x-if='debug'>
<div>
<label>clock: <input type='range'
step='1'
min='0'
max='1439'
x-model='userMinutes'> <span x-text='userTime'></span></label>
</div>
</template>
<header class='app-bar'>
<div class='app-bar__brand'>
<span class='app-bar__icon' aria-hidden='true'>&#9789;</span>
<span class='app-bar__title'
x-text="t('appTitle')"></span>
</div>
<div class='location-search'>
<input type='search'
class='location-search__input'
:placeholder="t('searchPlaceholder')"
x-model='searchQuery'
@input='onSearchInput'
@focus='searchOpen = searchResults.length > 0'
@click.outside='searchOpen = false'>
<template x-if='!selectedLocation'>
<button type='button'
class='location-search__locate'
:class="{'location-search__locate--busy': locating}"
:disabled='locating'
:title="locateError ? t(locateError) : t('useCurrentLocation')"
:aria-label="t('useCurrentLocation')"
@click='useCurrentLocation'>
<svg xmlns='http://www.w3.org/2000/svg'
width='1em'
height='1em'
viewBox='0 0 24 24'
aria-hidden='true'>
<path d='M0 0h24v24H0z'
fill='none' />
<path fill='currentColor'
d='M12 8.25a3.75 3.75 0 1 0 0 7.5a3.75 3.75 0 0 0 0-7.5' />
<path fill='currentColor'
fill-rule='evenodd'
d='M12 1.25a.75.75 0 0 1 .75.75v1.282a8.75 8.75 0 0 1 7.968 7.968H22a.75.75 0 0 1 0 1.5h-1.282a8.75 8.75 0 0 1-7.968 7.968V22a.75.75 0 0 1-1.5 0v-1.282a8.75 8.75 0 0 1-7.968-7.968H2a.75.75 0 0 1 0-1.5h1.282a8.75 8.75 0 0 1 7.968-7.968V2a.75.75 0 0 1 .75-.75M4.75 12a7.25 7.25 0 1 0 14.5 0a7.25 7.25 0 0 0-14.5 0'
clip-rule='evenodd' />
</svg>
</button>
</template>
<template x-if='searchOpen'>
<div class='location-search__dropdown'>
<template x-if='searchLoading'>
<div class='location-search__state'
x-text="t('searching')"></div>
</template>
<template x-if='!searchLoading && searchError'>
<div class='location-search__state'
x-text='t(searchError)'></div>
</template>
<template x-if='!searchLoading && !searchError && searchResults.length === 0'>
<div class='location-search__state'
x-text="t('noResults')"></div>
</template>
<template x-if='!searchLoading && !searchError && searchResults.length > 0'>
<ul class='location-search__results'>
<template x-for='location in searchResults'
:key='location.id'>
<li>
<button type='button'
class='location-search__item'
@click='selectLocation(location)'>
<span x-text='formatLocationLabel(location)'></span>
</button>
</li>
</template>
</ul>
</template>
</div>
</template>
</div>
</header>
<main class='app-main'>
<template x-if='todayTimes'>
<div class='current-salath text--center'>
<p>
<time :datetime='userNow'
x-text='formatDate(userNow)'></time>
</p>
<p>
<div class='salath-name-group salath-name-group--center'>
<span class='salath-name salath-name--primary'
:class="{'text--arabic': salathNameDisplay(todayTimes.currentSalath.salath).primary.lang === 'ar'}"
:lang='salathNameDisplay(todayTimes.currentSalath.salath).primary.lang'
x-text='salathNameDisplay(todayTimes.currentSalath.salath).primary.text'></span>
<div class="salath-name-alternatives">
<template x-for='item in salathNameDisplay(todayTimes.currentSalath.salath).secondary'
:key='item.lang'>
<span class='salath-name salath-name--secondary'
:class="{'text--arabic': item.lang === 'ar'}"
:lang='item.lang'
x-text='item.text'></span>
</template>
</div>
</div>
<p>
<time :datetime='todayTimes.nextSalath.startsAt'
class='text--numeric text--time'
x-text='todayTimes.nextSalath.untilHuman'></time>
</p>
</div>
</template>
<template x-if='todayTimes'>
<div class='table-wrapper'>
<table class='salath-table'>
<tbody>
<template x-for='it in todayTimes.times'>
<tr class='salath'
:class='{current: it.salath === todayTimes.currentSalath.salath}'>
<td class='cell-names'>
<div class='salath-name-group'>
<span class='salath-name salath-name--primary'
:class="{'text--arabic': salathNameDisplay(it.salath).primary.lang === 'ar'}"
:lang='salathNameDisplay(it.salath).primary.lang'
x-text='salathNameDisplay(it.salath).primary.text'></span>
<div class="salath-name-alternatives">
<template x-for='item in salathNameDisplay(it.salath).secondary'
:key='item.lang'>
<span class='salath-name salath-name--secondary'
:class="{'text--arabic': item.lang === 'ar'}"
:lang='item.lang'
x-text='item.text'></span>
</template>
</div>
</div>
</td>
<td class='cell-times'>
<span class='salath-time text--time text--numeric'
x-text='it.timeLocal'></span>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
</main>
<footer class='app-footer text--center text--numeric'>
<span class='clock'
x-text='formatTime(now)'></span>
</footer>
</div>
</body>
</html>