fine tune
This commit is contained in:
+4
-29
@@ -23,7 +23,6 @@ const startsWith = ref<string | null>(null)
|
|||||||
const preferredLanguage = ref<Language['code']>('fi')
|
const preferredLanguage = ref<Language['code']>('fi')
|
||||||
const lastSyncAt = ref<string | null>(null)
|
const lastSyncAt = ref<string | null>(null)
|
||||||
const isOnline = ref(navigator.onLine)
|
const isOnline = ref(navigator.onLine)
|
||||||
const isSyncing = ref(false)
|
|
||||||
const syncError = ref<string | null>(null)
|
const syncError = ref<string | null>(null)
|
||||||
const isMobile = ref(false)
|
const isMobile = ref(false)
|
||||||
const secondaryLanguage = ref<Language['code']>('en')
|
const secondaryLanguage = ref<Language['code']>('en')
|
||||||
@@ -112,13 +111,9 @@ const hasMissingTranslations = (entry: Entry) => {
|
|||||||
return languages.some((lang) => !entry[lang.code])
|
return languages.some((lang) => !entry[lang.code])
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredMissingCount = computed(() => {
|
|
||||||
return filteredEntries.value.filter((entry) => hasMissingTranslations(entry)).length
|
|
||||||
})
|
|
||||||
|
|
||||||
const lastSyncLabel = computed(() => {
|
const lastSyncLabel = computed(() => {
|
||||||
if (!lastSyncAt.value) {
|
if (!lastSyncAt.value) {
|
||||||
return 'Never synced'
|
return isOnline.value ? 'Never synced' : 'Waiting for internet access'
|
||||||
}
|
}
|
||||||
return new Date(lastSyncAt.value).toLocaleString()
|
return new Date(lastSyncAt.value).toLocaleString()
|
||||||
})
|
})
|
||||||
@@ -127,17 +122,6 @@ const alphaLetters = computed(() => {
|
|||||||
return Array.from({ length: 26 }, (_, index) => String.fromCharCode(65 + index))
|
return Array.from({ length: 26 }, (_, index) => String.fromCharCode(65 + index))
|
||||||
})
|
})
|
||||||
|
|
||||||
const clearFilters = () => {
|
|
||||||
categoryFilter.value = null
|
|
||||||
languageFilter.value = null
|
|
||||||
startsWith.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
const setLanguageFilter = (code: Language['code'] | null) => {
|
|
||||||
languageFilter.value = code
|
|
||||||
startsWith.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
const ensureSecondaryLanguage = () => {
|
const ensureSecondaryLanguage = () => {
|
||||||
if (secondaryLanguage.value === preferredLanguage.value) {
|
if (secondaryLanguage.value === preferredLanguage.value) {
|
||||||
const fallback = languages.find((lang) => lang.code !== preferredLanguage.value)
|
const fallback = languages.find((lang) => lang.code !== preferredLanguage.value)
|
||||||
@@ -156,16 +140,15 @@ const syncNow = async () => {
|
|||||||
if (!db.value) {
|
if (!db.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isSyncing.value = true
|
|
||||||
syncError.value = null
|
syncError.value = null
|
||||||
try {
|
try {
|
||||||
const result = await syncEntries(db.value)
|
const result = await syncEntries(db.value)
|
||||||
lastSyncAt.value = result.lastSyncAt ?? lastSyncAt.value
|
lastSyncAt.value = result.lastSyncAt ?? lastSyncAt.value
|
||||||
entries.value = listEntries(db.value)
|
entries.value = listEntries(db.value)
|
||||||
|
isOnline.value = true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
syncError.value = error instanceof Error ? error.message : 'Sync failed'
|
syncError.value = error instanceof Error ? error.message : 'Sync failed'
|
||||||
} finally {
|
isOnline.value = false
|
||||||
isSyncing.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,15 +198,7 @@ onBeforeUnmount(() => {
|
|||||||
<span class="brand-strong">Sanasto</span>
|
<span class="brand-strong">Sanasto</span>
|
||||||
<span class="brand-light">Wiki</span>
|
<span class="brand-light">Wiki</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-actions">
|
<div class="header-actions" />
|
||||||
<div class="status-pill" :class="{ offline: !isOnline }">
|
|
||||||
<span class="status-dot" />
|
|
||||||
<span>{{ isOnline ? 'Online' : 'Offline' }}</span>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary" :disabled="isSyncing" @click="syncNow">
|
|
||||||
{{ isSyncing ? 'Syncing…' : 'Sync now' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="header-sub">
|
<div class="header-sub">
|
||||||
<div class="meta-row">
|
<div class="meta-row">
|
||||||
|
|||||||
+6
-28
@@ -97,34 +97,6 @@ body {
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
border-radius: 999px;
|
|
||||||
border: 1px solid #bbf7d0;
|
|
||||||
background: #ecfdf3;
|
|
||||||
color: var(--emerald-600);
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-pill.offline {
|
|
||||||
border-color: #fecaca;
|
|
||||||
background: #fef2f2;
|
|
||||||
color: var(--red-500);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-dot {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: currentColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta-row {
|
.meta-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -210,6 +182,12 @@ body {
|
|||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-input[type='search']::-webkit-search-cancel-button,
|
||||||
|
.search-input[type='search']::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
.search-input:focus {
|
.search-input:focus {
|
||||||
outline: 2px solid rgba(79, 70, 229, 0.2);
|
outline: 2px solid rgba(79, 70, 229, 0.2);
|
||||||
border-color: var(--indigo-600);
|
border-color: var(--indigo-600);
|
||||||
|
|||||||
Reference in New Issue
Block a user