Fixes und Währungsumstellung
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
web:
|
web:
|
||||||
build: .
|
build: .
|
||||||
image: umrechner:v1.0.5
|
image: umrechner:v1.0.6
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- POCKETBASE_URL={$POCKETBASE_URL}
|
- POCKETBASE_URL={$POCKETBASE_URL}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{{/* Generischer Content Adapter fuer Einheitsumrechner */}}
|
{{/* Generischer Content Adapter fuer Einheitsumrechner */}}
|
||||||
{{/* Erzeugt alle from-to Permutationsseiten fuer linear, intermediate und runtime */}}
|
{{/* Erzeugt alle from-to Permutationsseiten fuer linear, temperatures und currencies */}}
|
||||||
|
|
||||||
{{ $pbBase := getenv "POCKETBASE_URL" | default site.Params.pocketbase_url }}
|
{{ $pbBase := getenv "POCKETBASE_URL" | default site.Params.pocketbase_url }}
|
||||||
{{ $pbUrl := printf "%s/api/collections/currencies/records" $pbBase }}
|
{{ $pbUrl := printf "%s/api/collections/currencies/records" $pbBase }}
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
{{ $categorySlug := $categoryData.slug }}
|
{{ $categorySlug := $categoryData.slug }}
|
||||||
{{ $units := $categoryData.units }}
|
{{ $units := $categoryData.units }}
|
||||||
|
|
||||||
{{ if eq $engine "runtime" }}
|
{{ if eq $engine "currencies" }}
|
||||||
{{ if not $pbOk }}{{ continue }}{{ end }}
|
{{ if not $pbOk }}{{ continue }}{{ end }}
|
||||||
{{ $pbCurrencies := slice }}
|
{{ $pbCurrencies := slice }}
|
||||||
{{ range $record := $pbData }}
|
{{ range $record := $pbData }}
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
"to_name" $toName
|
"to_name" $toName
|
||||||
"slug" $slug
|
"slug" $slug
|
||||||
"description" $description
|
"description" $description
|
||||||
"engine" "runtime"
|
"engine" "currencies"
|
||||||
"rate" $rate
|
"rate" $rate
|
||||||
"rates_updated" $latestUpdate
|
"rates_updated" $latestUpdate
|
||||||
}}
|
}}
|
||||||
@@ -121,11 +121,21 @@
|
|||||||
"from_factor" $fromData.factor
|
"from_factor" $fromData.factor
|
||||||
"to_factor" $toData.factor
|
"to_factor" $toData.factor
|
||||||
) }}
|
) }}
|
||||||
{{ else if eq $engine "intermediate" }}
|
{{ else if eq $engine "temperatures" }}
|
||||||
|
{{ $convertFormulas := $categoryData.convertFormulas }}
|
||||||
|
{{ $formula := "" }}
|
||||||
|
{{ with index $convertFormulas $fromUnit }}
|
||||||
|
{{ $formula = index . $toUnit }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $displayFormulas := $categoryData.formulas }}
|
||||||
|
{{ $displayFormula := "" }}
|
||||||
|
{{ with index $displayFormulas $fromUnit }}
|
||||||
|
{{ $displayFormula = index . $toUnit }}
|
||||||
|
{{ end }}
|
||||||
{{ $params = merge $params (dict
|
{{ $params = merge $params (dict
|
||||||
"engine" "intermediate"
|
"engine" "temperatures"
|
||||||
"from_unit" $fromUnit
|
"convertFormula" $formula
|
||||||
"to_unit" $toUnit
|
"displayFormula" $displayFormula
|
||||||
) }}
|
) }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|||||||
@@ -8,20 +8,7 @@
|
|||||||
"rankine",
|
"rankine",
|
||||||
"reaumur"
|
"reaumur"
|
||||||
],
|
],
|
||||||
"conversion_engine": "intermediate",
|
"conversion_engine": "temperatures",
|
||||||
"intermediate_unit": "celsius",
|
|
||||||
"to_intermediate": {
|
|
||||||
"fahrenheit": "(v - 32) * 5/9",
|
|
||||||
"kelvin": "v - 273.15",
|
|
||||||
"rankine": "(v - 491.67) * 5/9",
|
|
||||||
"reaumur": "v * 5/4"
|
|
||||||
},
|
|
||||||
"from_intermediate": {
|
|
||||||
"fahrenheit": "v * 9/5 + 32",
|
|
||||||
"kelvin": "v + 273.15",
|
|
||||||
"rankine": "(v + 273.15) * 9/5",
|
|
||||||
"reaumur": "v * 4/5"
|
|
||||||
},
|
|
||||||
"units": {
|
"units": {
|
||||||
"celsius": {
|
"celsius": {
|
||||||
"name": "Celsius"
|
"name": "Celsius"
|
||||||
@@ -38,5 +25,69 @@
|
|||||||
"reaumur": {
|
"reaumur": {
|
||||||
"name": "Réaumur"
|
"name": "Réaumur"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"formulas": {
|
||||||
|
"celsius": {
|
||||||
|
"fahrenheit": "Fahrenheit = Celsius × 9/5 + 32",
|
||||||
|
"kelvin": "Kelvin = Celsius + 273,15",
|
||||||
|
"rankine": "Rankine = (Celsius + 273,15) × 9/5",
|
||||||
|
"reaumur": "Réaumur = Celsius × 4/5"
|
||||||
|
},
|
||||||
|
"fahrenheit": {
|
||||||
|
"celsius": "Celsius = (Fahrenheit − 32) × 5/9",
|
||||||
|
"kelvin": "Kelvin = (Fahrenheit − 32) × 5/9 + 273,15",
|
||||||
|
"rankine": "Rankine = Fahrenheit + 459,67",
|
||||||
|
"reaumur": "Réaumur = (Fahrenheit − 32) × 4/9"
|
||||||
|
},
|
||||||
|
"kelvin": {
|
||||||
|
"celsius": "Celsius = Kelvin − 273,15",
|
||||||
|
"fahrenheit": "Fahrenheit = (Kelvin − 273,15) × 9/5 + 32",
|
||||||
|
"rankine": "Rankine = Kelvin × 9/5",
|
||||||
|
"reaumur": "Réaumur = (Kelvin − 273,15) × 4/5"
|
||||||
|
},
|
||||||
|
"rankine": {
|
||||||
|
"celsius": "Celsius = (Rankine − 491,67) × 5/9",
|
||||||
|
"fahrenheit": "Fahrenheit = Rankine − 459,67",
|
||||||
|
"kelvin": "Kelvin = Rankine × 5/9",
|
||||||
|
"reaumur": "Réaumur = (Rankine − 491,67) × 4/9"
|
||||||
|
},
|
||||||
|
"reaumur": {
|
||||||
|
"celsius": "Celsius = Réaumur × 5/4",
|
||||||
|
"fahrenheit": "Fahrenheit = Réaumur × 9/4 + 32",
|
||||||
|
"kelvin": "Kelvin = Réaumur × 5/4 + 273,15",
|
||||||
|
"rankine": "Rankine = (Réaumur × 5/4 + 273,15) × 9/5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"convertFormulas": {
|
||||||
|
"celsius": {
|
||||||
|
"fahrenheit": "v => v.times(9).dividedBy(5).plus(32)",
|
||||||
|
"kelvin": "v => v.plus(273.15)",
|
||||||
|
"rankine": "v => v.plus(273.15).times(9).dividedBy(5)",
|
||||||
|
"reaumur": "v => v.times(4).dividedBy(5)"
|
||||||
|
},
|
||||||
|
"fahrenheit": {
|
||||||
|
"celsius": "v => v.minus(32).times(5).dividedBy(9)",
|
||||||
|
"kelvin": "v => v.minus(32).times(5).dividedBy(9).plus(273.15)",
|
||||||
|
"rankine": "v => v.plus(459.67)",
|
||||||
|
"reaumur": "v => v.minus(32).times(4).dividedBy(9)"
|
||||||
|
},
|
||||||
|
"kelvin": {
|
||||||
|
"celsius": "v => v.minus(273.15)",
|
||||||
|
"fahrenheit": "v => v.minus(273.15).times(9).dividedBy(5).plus(32)",
|
||||||
|
"rankine": "v => v.times(9).dividedBy(5)",
|
||||||
|
"reaumur": "v => v.minus(273.15).times(4).dividedBy(5)"
|
||||||
|
},
|
||||||
|
"rankine": {
|
||||||
|
"celsius": "v => v.minus(491.67).times(5).dividedBy(9)",
|
||||||
|
"fahrenheit": "v => v.minus(459.67)",
|
||||||
|
"kelvin": "v => v.times(5).dividedBy(9)",
|
||||||
|
"reaumur": "v => v.minus(491.67).times(4).dividedBy(9)"
|
||||||
|
},
|
||||||
|
"reaumur": {
|
||||||
|
"celsius": "v => v.times(5).dividedBy(4)",
|
||||||
|
"fahrenheit": "v => v.times(9).dividedBy(4).plus(32)",
|
||||||
|
"kelvin": "v => v.times(5).dividedBy(4).plus(273.15)",
|
||||||
|
"rankine": "v => v.times(5).dividedBy(4).plus(273.15).times(9).dividedBy(5)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
"php",
|
"php",
|
||||||
"egp"
|
"egp"
|
||||||
],
|
],
|
||||||
"conversion_engine": "runtime",
|
"conversion_engine": "currencies",
|
||||||
"units": {
|
"units": {
|
||||||
"eur": {
|
"eur": {
|
||||||
"name": "Euro"
|
"name": "Euro"
|
||||||
|
|||||||
@@ -1,36 +1,21 @@
|
|||||||
{{ define "main" }}
|
{{ define "main" }}
|
||||||
{{ $catData := index hugo.Data .Params.category }}
|
{{ $catData := index hugo.Data .Params.category }}
|
||||||
{{ $config := "" }}
|
|
||||||
{{ if eq .Params.engine "linear" }}
|
|
||||||
{{ $config = dict "fromFactor" .Params.from_factor
|
|
||||||
"toFactor" .Params.to_factor | jsonify }}
|
|
||||||
{{ else if eq .Params.engine "intermediate" }}
|
|
||||||
{{ $toExpr := index $catData.to_intermediate
|
|
||||||
.Params.from | default "v" }}
|
|
||||||
{{ $fromExpr := index $catData.from_intermediate
|
|
||||||
.Params.to | default "v" }}
|
|
||||||
{{ $config = printf
|
|
||||||
"{ toIntermediate: v => %s, fromIntermediate: v => %s }"
|
|
||||||
$toExpr $fromExpr }}
|
|
||||||
{{ else if eq .Params.engine "runtime" }}
|
|
||||||
{{ $fromCode := .Params.from }}
|
|
||||||
{{ $toCode := .Params.to }}
|
|
||||||
{{ $config = printf
|
|
||||||
"{ init: async function () { const pbUrl = document.querySelector('meta[name=\\'pocketbase-url\\']')?.content || 'https://www.alphabreed.com'; try { const response = await fetch(`${pbUrl}/api/collections/currencies/records`); if (!response.ok) { this.ratesError = 'Wechselkurse konnten nicht geladen werden.'; return; } const data = await response.json(); let latestUpdate = ''; for (const item of data.items || []) { this.rates[item.id] = item.rate; if (!latestUpdate || item.updated > latestUpdate) { latestUpdate = item.updated; } } const fromRate = '%s' === 'eur' ? 1 : this.rates['%s']; const toRate = '%s' === 'eur' ? 1 : this.rates['%s']; if (fromRate && toRate) { this.currentRate = parseFloat(toRate) / parseFloat(fromRate); } if (latestUpdate) { this.ratesUpdated = new Date(latestUpdate).toLocaleString('de-DE', { day: '2-digit', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit' }); } } catch (e) { this.ratesError = 'Wechselkurse konnten nicht geladen werden.'; } }, convert: function (value) { const fromRate = '%s' === 'eur' ? 1 : this.rates['%s']; const toRate = '%s' === 'eur' ? 1 : this.rates['%s']; if (!fromRate || !toRate) { return null; } return value.times(new Decimal(toRate)).dividedBy(new Decimal(fromRate)); } }"
|
|
||||||
$fromCode $fromCode $toCode $toCode
|
|
||||||
$fromCode $fromCode $toCode $toCode }}
|
|
||||||
{{ end }}
|
|
||||||
{{ $availableUnits := partial "available-units.html"
|
{{ $availableUnits := partial "available-units.html"
|
||||||
(dict "category" .Params.category "units" $catData.units) }}
|
(dict "category" .Params.category "units" $catData.units) }}
|
||||||
|
|
||||||
<div x-data="createConverter('{{ .Params.engine }}',
|
{{ $engine := .Params.engine | default "linear" }}
|
||||||
{{ $config | safeJS }})"
|
|
||||||
x-init="init()">
|
{{ if eq $engine "currencies" }}
|
||||||
|
{{ partial "conversion/currencies-data" . }}
|
||||||
|
{{ else if eq $engine "temperatures" }}
|
||||||
|
{{ partial "conversion/temperatures-data" . }}
|
||||||
|
{{ else }}
|
||||||
|
{{ partial "conversion/linear-data" . }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
<div id="conversionform"
|
<div id="conversionform"
|
||||||
class="bg-white p-8 rounded-lg shadow-md w-full
|
class="bg-white p-8 rounded-lg shadow-md w-full
|
||||||
dark:bg-gray-700 dark:text-grey-200"
|
dark:bg-gray-700 dark:text-grey-200">
|
||||||
x-data="navActions()">
|
|
||||||
|
|
||||||
<h1 id="headline"
|
<h1 id="headline"
|
||||||
class="text-2xl font-bold mb-6 text-center">
|
class="text-2xl font-bold mb-6 text-center">
|
||||||
@@ -40,18 +25,13 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<a x-ref="ajaxLink"
|
|
||||||
x-target.push="maincontent"
|
|
||||||
href="/"
|
|
||||||
class="hidden"></a>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="type"
|
<label for="type"
|
||||||
class="block text-sm font-medium opacity-75">
|
class="block text-sm font-medium opacity-75">
|
||||||
Einheitentyp:
|
Einheitentyp:
|
||||||
</label>
|
</label>
|
||||||
<select id="type" name="type"
|
<select id="type" name="type"
|
||||||
@change="navigate($event.target.value)"
|
@change="navigate($event.target.value, '1')"
|
||||||
class="select mt-1 block w-full">
|
class="select mt-1 block w-full">
|
||||||
{{ range $slug, $data := hugo.Data }}
|
{{ range $slug, $data := hugo.Data }}
|
||||||
{{ if and $data.slug $data.name }}
|
{{ if and $data.slug $data.name }}
|
||||||
@@ -79,8 +59,8 @@
|
|||||||
Umrechnen von:
|
Umrechnen von:
|
||||||
</label>
|
</label>
|
||||||
<select id="from" name="from"
|
<select id="from" name="from"
|
||||||
@change="navigateWithValue(
|
@change="navigate(
|
||||||
$event.target.value)"
|
$event.target.value, inputValue)"
|
||||||
class="select mt-1 block w-full">
|
class="select mt-1 block w-full">
|
||||||
{{ range $catData.unitOrder }}
|
{{ range $catData.unitOrder }}
|
||||||
{{ $unitData := index $availableUnits . }}
|
{{ $unitData := index $availableUnits . }}
|
||||||
@@ -98,8 +78,8 @@
|
|||||||
|
|
||||||
<div class="text-center sm:pt-6">
|
<div class="text-center sm:pt-6">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
@click="navigateWithResult(
|
@click="navigate(
|
||||||
$el.dataset.swapUrl)"
|
$el.dataset.swapUrl, prettyNumber(convert(prepareValue(inputValue))))"
|
||||||
data-swap-url="/{{ .Params.to }}-in-{{ .Params.from }}/"
|
data-swap-url="/{{ .Params.to }}-in-{{ .Params.from }}/"
|
||||||
class="inline-flex items-center text-sm
|
class="inline-flex items-center text-sm
|
||||||
font-medium text-primary
|
font-medium text-primary
|
||||||
@@ -110,8 +90,7 @@
|
|||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
class="w-6 h-6">
|
class="w-6 h-6">
|
||||||
<path stroke-linecap="round"
|
<path stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3
|
||||||
d="M7.5 21 3 16.5m0 0L7.5 12M3
|
|
||||||
16.5h13.5m0-13.5L21 7.5m0
|
16.5h13.5m0-13.5L21 7.5m0
|
||||||
0L16.5 12M21 7.5H7.5" />
|
0L16.5 12M21 7.5H7.5" />
|
||||||
</svg>
|
</svg>
|
||||||
@@ -125,8 +104,8 @@
|
|||||||
Umrechnen in:
|
Umrechnen in:
|
||||||
</label>
|
</label>
|
||||||
<select id="to" name="to"
|
<select id="to" name="to"
|
||||||
@change="navigateWithValue(
|
@change="navigate(
|
||||||
$event.target.value)"
|
$event.target.value, inputValue)"
|
||||||
class="select mt-1 block w-full">
|
class="select mt-1 block w-full">
|
||||||
{{ range $catData.unitOrder }}
|
{{ range $catData.unitOrder }}
|
||||||
{{ $unitData := index $availableUnits . }}
|
{{ $unitData := index $availableUnits . }}
|
||||||
@@ -155,7 +134,7 @@
|
|||||||
<input type="text" id="value"
|
<input type="text" id="value"
|
||||||
inputmode="decimal"
|
inputmode="decimal"
|
||||||
x-model="inputValue"
|
x-model="inputValue"
|
||||||
@input="calculate()"
|
@input.debounce.500ms="updateUrl(inputValue)"
|
||||||
class="textinput mt-1 block w-full"
|
class="textinput mt-1 block w-full"
|
||||||
placeholder="Wert eingeben">
|
placeholder="Wert eingeben">
|
||||||
</div>
|
</div>
|
||||||
@@ -166,13 +145,8 @@
|
|||||||
</label>
|
</label>
|
||||||
<input type="text" id="result"
|
<input type="text" id="result"
|
||||||
disabled
|
disabled
|
||||||
:value="result"
|
:value="prettyNumber(convert(prepareValue(inputValue)))"
|
||||||
class="textinput mt-1 block w-full">
|
class="textinput mt-1 block w-full">
|
||||||
<p x-show="ratesError"
|
|
||||||
x-cloak
|
|
||||||
class="text-sm text-red-600 mt-1
|
|
||||||
dark:text-red-400"
|
|
||||||
x-text="ratesError"></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -188,5 +162,3 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,24 +48,32 @@
|
|||||||
{{ replace $fromI "v" $intermediateName 1 }}</b>
|
{{ replace $fromI "v" $intermediateName 1 }}</b>
|
||||||
</p>
|
</p>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ else if eq .Params.engine "runtime" }}
|
{{ else if eq .Params.engine "temperatures" }}
|
||||||
<p class="mb-4 mt-8">
|
<p class="mb-4 mt-8">
|
||||||
Die Umrechnung von {{ $fromName }} in {{ $toName }}
|
Die Umrechnung von {{ $fromName }} in {{ $toName }}
|
||||||
erfolgt mittels dieser Formel:
|
erfolgt mittels dieser Formel:
|
||||||
</p>
|
</p>
|
||||||
<div x-show="currentRate > 0">
|
<p class="text-lg text-primary dark:text-primary-light">
|
||||||
|
<b>{{ .Params.displayFormula }}</b>
|
||||||
|
</p>
|
||||||
|
{{ else if eq .Params.engine "currencies" }}
|
||||||
|
<p class="mb-4 mt-8">
|
||||||
|
Die Umrechnung von {{ $fromName }} in {{ $toName }}
|
||||||
|
erfolgt mittels dieser Formel:
|
||||||
|
</p>
|
||||||
|
<div x-show="rate > 0">
|
||||||
<p class="text-lg text-primary dark:text-primary-light"
|
<p class="text-lg text-primary dark:text-primary-light"
|
||||||
x-show="currentRate >= 1">
|
x-show="rate >= 1">
|
||||||
<b x-text="'{{ $toName }} = {{ $fromName }} × '
|
<b x-text="'{{ $toName }} = {{ $fromName }} × '
|
||||||
+ prettyNumber(currentRate)"></b>
|
+ prettyNumber(rate)"></b>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-lg text-primary dark:text-primary-light"
|
<p class="text-lg text-primary dark:text-primary-light"
|
||||||
x-show="currentRate < 1">
|
x-show="rate < 1">
|
||||||
<b x-text="'{{ $toName }} = {{ $fromName }} / '
|
<b x-text="'{{ $toName }} = {{ $fromName }} / '
|
||||||
+ prettyNumber(1 / currentRate)"></b>
|
+ prettyNumber(1 / rate)"></b>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div x-show="!currentRate">
|
<div x-show="!rate">
|
||||||
{{ $rate := float .Params.rate }}
|
{{ $rate := float .Params.rate }}
|
||||||
{{ if ge $rate 1 }}
|
{{ if ge $rate 1 }}
|
||||||
<p class="text-lg text-primary dark:text-primary-light">
|
<p class="text-lg text-primary dark:text-primary-light">
|
||||||
|
|||||||
40
hugo/layouts/partials/conversion/currencies-data.html
Normal file
40
hugo/layouts/partials/conversion/currencies-data.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<div x-data="{
|
||||||
|
inputValue: '1',
|
||||||
|
rate: 0,
|
||||||
|
formula: '',
|
||||||
|
ratesError: '',
|
||||||
|
ratesUpdated: '',
|
||||||
|
convert(v) { return v.times(this.rate); },
|
||||||
|
async init() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const valueParam = params.get('v');
|
||||||
|
if (valueParam) this.inputValue = valueParam.replace(/,/g, '.');
|
||||||
|
|
||||||
|
const pbUrl = document.querySelector('meta[name=\'pocketbase-url\']')?.content || 'https://www.alphabreed.com';
|
||||||
|
try {
|
||||||
|
const response = await fetch(pbUrl + '/api/collections/currencies/records');
|
||||||
|
if (!response.ok) {
|
||||||
|
this.ratesError = 'Wechselkurse konnten nicht geladen werden.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
const rates = {};
|
||||||
|
let updated = '';
|
||||||
|
for (const item of data.items || []) {
|
||||||
|
rates[item.id] = item.rate;
|
||||||
|
updated = item.updated;
|
||||||
|
}
|
||||||
|
const fromRate = '{{ .Params.from }}' === 'eur' ? 1 : rates['{{ .Params.from }}'];
|
||||||
|
const toRate = '{{ .Params.to }}' === 'eur' ? 1 : rates['{{ .Params.to }}'];
|
||||||
|
if (fromRate && toRate) {
|
||||||
|
this.rate = parseFloat(toRate) / parseFloat(fromRate);
|
||||||
|
this.ratesUpdated = new Date(updated).toLocaleString('de-DE', { day: '2-digit', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit' });
|
||||||
|
this.formula = '1 {{ .Params.from | upper }} = ' + prettyNumber(this.rate) + ' {{ .Params.to | upper }}';
|
||||||
|
} else {
|
||||||
|
this.ratesError = 'Wechselkurse nicht gefunden.';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.ratesError = 'Wechselkurse konnten nicht geladen werden.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}">
|
||||||
9
hugo/layouts/partials/conversion/linear-data.html
Normal file
9
hugo/layouts/partials/conversion/linear-data.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div x-data="{
|
||||||
|
inputValue: '1',
|
||||||
|
convert: v => new Decimal(v).times({{ .Params.from_factor }}).dividedBy({{ .Params.to_factor }}),
|
||||||
|
async init() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const valueParam = params.get('v');
|
||||||
|
if (valueParam) this.inputValue = valueParam.replace(/,/g, '.');
|
||||||
|
}
|
||||||
|
}" x-init="init()">
|
||||||
9
hugo/layouts/partials/conversion/temperatures-data.html
Normal file
9
hugo/layouts/partials/conversion/temperatures-data.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div x-data="{
|
||||||
|
inputValue: '1',
|
||||||
|
convert: {{ .Params.convertFormula | safeJS }},
|
||||||
|
async init() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const valueParam = params.get('v');
|
||||||
|
if (valueParam) this.inputValue = valueParam.replace(/,/g, '.');
|
||||||
|
}
|
||||||
|
}" x-init="init()">
|
||||||
@@ -1,107 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
|
||||||
* Alpine.js navigation helpers for conversion page.
|
|
||||||
* Handles navigation via hidden AJAX link.
|
|
||||||
*/
|
|
||||||
function navActions() {
|
|
||||||
return {
|
|
||||||
navigate(url) {
|
|
||||||
this.$refs.ajaxLink.href = url;
|
|
||||||
this.$nextTick(() => this.$refs.ajaxLink.click());
|
|
||||||
},
|
|
||||||
navigateWithValue(url) {
|
|
||||||
const el = document.getElementById('value');
|
|
||||||
const val = el ? el.value.replace(/,/g, '.') : '1';
|
|
||||||
this.$refs.ajaxLink.href = url + '?v=' + val;
|
|
||||||
this.$nextTick(() => this.$refs.ajaxLink.click());
|
|
||||||
},
|
|
||||||
navigateWithResult(url) {
|
|
||||||
const el = document.getElementById('result');
|
|
||||||
const val = el ? el.value.replace(/,/g, '.') : '';
|
|
||||||
if (val) {
|
|
||||||
this.$refs.ajaxLink.href = url + '?v=' + val;
|
|
||||||
} else {
|
|
||||||
this.$refs.ajaxLink.href = url;
|
|
||||||
}
|
|
||||||
this.$nextTick(() => this.$refs.ajaxLink.click());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory function for Alpine.js converter components.
|
|
||||||
* @param {string} engine - 'linear', 'intermediate' or 'runtime'
|
|
||||||
* @param {object} config - Engine-specific configuration
|
|
||||||
* @returns {object} Alpine component data
|
|
||||||
*/
|
|
||||||
function createConverter(engine, config) {
|
|
||||||
return {
|
|
||||||
inputValue: '1',
|
|
||||||
result: '',
|
|
||||||
rates: {},
|
|
||||||
ratesError: '',
|
|
||||||
ratesUpdated: '',
|
|
||||||
currentRate: 0,
|
|
||||||
async init() {
|
|
||||||
const params = new URLSearchParams(
|
|
||||||
window.location.search);
|
|
||||||
const valueParam = params.get('v');
|
|
||||||
if (valueParam) {
|
|
||||||
this.inputValue = valueParam.replace(/,/g, '.');
|
|
||||||
}
|
|
||||||
this.$watch('inputValue', val => {
|
|
||||||
if (val && val.indexOf(',') !== -1) {
|
|
||||||
this.inputValue = val.replace(/,/g, '.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (typeof config.init === 'function') {
|
|
||||||
await config.init.call(this);
|
|
||||||
}
|
|
||||||
this.calculate();
|
|
||||||
},
|
|
||||||
calculate() {
|
|
||||||
try {
|
|
||||||
const normalized = parseNumber(this.inputValue);
|
|
||||||
if (!normalized || isNaN(normalized)) {
|
|
||||||
this.result = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const value = new Decimal(normalized);
|
|
||||||
let rawResult;
|
|
||||||
if (typeof config.convert === 'function') {
|
|
||||||
rawResult = config.convert.call(this, value);
|
|
||||||
} else if (engine === 'linear') {
|
|
||||||
const fromFactor = new Decimal(
|
|
||||||
config.fromFactor);
|
|
||||||
const toFactor = new Decimal(
|
|
||||||
config.toFactor);
|
|
||||||
rawResult = value.times(fromFactor)
|
|
||||||
.dividedBy(toFactor);
|
|
||||||
} else if (engine === 'intermediate') {
|
|
||||||
let v = value.toNumber();
|
|
||||||
v = config.toIntermediate(v);
|
|
||||||
v = config.fromIntermediate(v);
|
|
||||||
rawResult = new Decimal(v);
|
|
||||||
} else {
|
|
||||||
this.result = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.result = prettyNumber(rawResult);
|
|
||||||
const normalizedInputValue = this.inputValue
|
|
||||||
.replace(/,/g, '.');
|
|
||||||
if (normalizedInputValue
|
|
||||||
&& normalizedInputValue !== '0') {
|
|
||||||
history.replaceState(
|
|
||||||
null, '', '?v=' + normalizedInputValue);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.result = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a number as plain digits with dot as decimal separator.
|
* Formats a number as plain digits with dot as decimal separator.
|
||||||
* @param {Decimal|string|number} num
|
* @param {Decimal|string|number} num
|
||||||
@@ -126,7 +24,7 @@ function prettyNumber(num, minPrecision, maxPrecision) {
|
|||||||
// Larger numbers need fewer decimal places for readable output;
|
// Larger numbers need fewer decimal places for readable output;
|
||||||
// smaller numbers get more to stay meaningful.
|
// smaller numbers get more to stay meaningful.
|
||||||
let precision = maxPrecision;
|
let precision = maxPrecision;
|
||||||
if (absVal.gte(1000000)) {
|
if (absVal.gte(10000)) {
|
||||||
precision = 2;
|
precision = 2;
|
||||||
} else if (absVal.gte(1000)) {
|
} else if (absVal.gte(1000)) {
|
||||||
precision = 4;
|
precision = 4;
|
||||||
@@ -160,3 +58,39 @@ function parseNumber(input) {
|
|||||||
}
|
}
|
||||||
return input.replace(/,/g, '.') || '0';
|
return input.replace(/,/g, '.') || '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares input value for conversion.
|
||||||
|
* Returns a Decimal, or 1 if input is empty.
|
||||||
|
* @param {string} input - User input from field
|
||||||
|
* @returns {Decimal} Prepared value
|
||||||
|
*/
|
||||||
|
function prepareValue(input) {
|
||||||
|
if (!input || input.trim() === '') {
|
||||||
|
return new Decimal(1);
|
||||||
|
}
|
||||||
|
return new Decimal(input.replace(/,/g, '.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the URL with the current input value.
|
||||||
|
* @param {string} value - The input value
|
||||||
|
*/
|
||||||
|
function updateUrl(value) {
|
||||||
|
const normalized = value ? value.replace(/,/g, '.') : '';
|
||||||
|
if (normalized && normalized !== '0') {
|
||||||
|
history.replaceState(null, '', '?v=' + normalized);
|
||||||
|
} else {
|
||||||
|
history.replaceState(null, '', '?v=1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to a new URL with the current input value as parameter.
|
||||||
|
* @param {string} url - Target URL
|
||||||
|
* @param {string} value - Current input value
|
||||||
|
*/
|
||||||
|
function navigate(url, value) {
|
||||||
|
const normalized = value ? value.replace(/,/g, '.') : '1';
|
||||||
|
window.location.href = url + '?v=' + normalized;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user