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.
191 lines
8.3 KiB
HTML
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'>☽</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>
|