@jjlmoya/utils-drones 1.31.0 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/i18n/en.ts +1 -1
- package/src/category/i18n/fr.ts +1 -1
- package/src/components/PreviewNavSidebar.astro +116 -116
- package/src/components/PreviewToolbar.astro +143 -143
- package/src/data.ts +1 -1
- package/src/env.d.ts +1 -1
- package/src/layouts/PreviewLayout.astro +118 -118
- package/src/pages/[locale].astro +251 -251
- package/src/pages/index.astro +4 -4
- package/src/tests/faq_count.test.ts +1 -1
- package/src/tests/mocks/astro_mock.js +1 -1
- package/src/tests/no_h1_in_components.test.ts +1 -1
- package/src/tests/tool_validation.test.ts +15 -15
- package/src/tool/antenna-length-calculator/bibliography.astro +6 -6
- package/src/tool/antenna-length-calculator/component.astro +329 -329
- package/src/tool/antenna-length-calculator/seo.astro +15 -15
- package/src/tool/drone-battery-c-rating-calculator/i18n/de.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/en.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/es.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/id.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/ja.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/ko.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/nl.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/pl.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/ru.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/sv.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/tr.ts +192 -192
- package/src/tool/drone-battery-c-rating-calculator/i18n/zh.ts +192 -192
- package/src/tool/drone-flight-time/component.astro +187 -187
- package/src/tool/drone-flight-time/seo.astro +15 -15
- package/src/tool/drone-motor-propeller-calculator/seo.astro +7 -4
- package/src/tool/gps-coordinates-converter/component.astro +275 -275
- package/src/tool/gps-coordinates-converter/seo.astro +15 -15
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
---
|
|
2
|
-
const { ui } = Astro.props;
|
|
3
|
-
import BatterySpecs from "./components/BatterySpecs.astro";
|
|
4
|
-
import ConsumptionStats from "./components/ConsumptionStats.astro";
|
|
5
|
-
import FlightDashboard from "./components/FlightDashboard.astro";
|
|
6
|
-
import AutonomyChart from "./components/AutonomyChart.astro";
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
<div class="flight-calculator-ui">
|
|
10
|
-
<div class="tech-mega-card animate-in fade-in zoom-in duration-700">
|
|
11
|
-
<div class="card-grid">
|
|
12
|
-
<div class="config-sidebar">
|
|
13
|
-
<BatterySpecs ui={ui} />
|
|
14
|
-
<div class="divider"></div>
|
|
15
|
-
<ConsumptionStats ui={ui} />
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<div class="main-display">
|
|
19
|
-
<FlightDashboard ui={ui} />
|
|
20
|
-
<div class="divider"></div>
|
|
21
|
-
<AutonomyChart ui={ui} />
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<script>
|
|
28
|
-
import { Chart, registerables } from "chart.js";
|
|
29
|
-
Chart.register(...registerables);
|
|
30
|
-
|
|
31
|
-
const capInput = document.getElementById("capacityInput") as HTMLInputElement;
|
|
32
|
-
const cellsInput = document.getElementById("cellsInput") as HTMLSelectElement;
|
|
33
|
-
const safetyInput = document.getElementById("safetyInput") as HTMLInputElement;
|
|
34
|
-
const drawInput = document.getElementById("drawInput") as HTMLInputElement;
|
|
35
|
-
const wattsInput = document.getElementById("wattsInput") as HTMLInputElement;
|
|
36
|
-
const effInput = document.getElementById("efficiencyInput") as HTMLInputElement;
|
|
37
|
-
|
|
38
|
-
const displays = {
|
|
39
|
-
cap: document.getElementById("capDisplay"),
|
|
40
|
-
cells: document.getElementById("cellsDisplay"),
|
|
41
|
-
volts: document.getElementById("voltsDisplay"),
|
|
42
|
-
safety: document.getElementById("safetyDisplay"),
|
|
43
|
-
draw: document.getElementById("drawDisplay"),
|
|
44
|
-
watts: document.getElementById("wattsDisplay"),
|
|
45
|
-
eff: document.getElementById("effDisplay"),
|
|
46
|
-
timeMain: document.getElementById("timeMainDisplay"),
|
|
47
|
-
timeTotal: document.getElementById("timeTotalDisplay"),
|
|
48
|
-
wh: document.getElementById("whDisplay"),
|
|
49
|
-
co2: document.getElementById("co2Display"),
|
|
50
|
-
circle: document.getElementById("timeCircle")
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
let chart: Chart | null = null;
|
|
54
|
-
|
|
55
|
-
function getChartConfig(label: string) {
|
|
56
|
-
return {
|
|
57
|
-
type: "line",
|
|
58
|
-
data: {
|
|
59
|
-
labels: [],
|
|
60
|
-
datasets: [{
|
|
61
|
-
label,
|
|
62
|
-
data: [],
|
|
63
|
-
borderColor: "#f59e0b",
|
|
64
|
-
backgroundColor: "rgba(245, 158, 11, 0.1)",
|
|
65
|
-
borderWidth: 3,
|
|
66
|
-
fill: true,
|
|
67
|
-
tension: 0.4,
|
|
68
|
-
pointRadius: 0,
|
|
69
|
-
pointHitRadius: 10
|
|
70
|
-
}]
|
|
71
|
-
},
|
|
72
|
-
options: {
|
|
73
|
-
responsive: true,
|
|
74
|
-
maintainAspectRatio: false,
|
|
75
|
-
plugins: { legend: { display: false } },
|
|
76
|
-
scales: {
|
|
77
|
-
y: { beginAtZero: true, grid: { color: "rgba(0,0,0,0.05)" } },
|
|
78
|
-
x: { grid: { display: false } }
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function initChart() {
|
|
85
|
-
const canvas = document.getElementById("autonomyChart") as HTMLCanvasElement;
|
|
86
|
-
const ctx = canvas?.getContext("2d");
|
|
87
|
-
if (!ctx) return;
|
|
88
|
-
const chartLabel = canvas.dataset.label || "Minutos";
|
|
89
|
-
chart = new Chart(ctx, getChartConfig(chartLabel));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function calculate(source: string) {
|
|
93
|
-
const cap = parseFloat(capInput.value);
|
|
94
|
-
const cells = parseInt(cellsInput.value);
|
|
95
|
-
const safety = parseFloat(safetyInput.value) / 100;
|
|
96
|
-
let draw = parseFloat(drawInput.value);
|
|
97
|
-
const voltage = cells * 3.7;
|
|
98
|
-
|
|
99
|
-
if (source === 'watts') {
|
|
100
|
-
draw = parseFloat(wattsInput.value) / voltage;
|
|
101
|
-
drawInput.value = draw.toFixed(1);
|
|
102
|
-
} else {
|
|
103
|
-
wattsInput.value = (draw * voltage).toFixed(1);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const state = { cap, cells, safety, draw, voltage };
|
|
107
|
-
updateDisplays(state);
|
|
108
|
-
|
|
109
|
-
const usableAh = (cap / 1000) * safety;
|
|
110
|
-
const totalAh = cap / 1000;
|
|
111
|
-
|
|
112
|
-
const safeTimeMin = (usableAh / draw) * 60;
|
|
113
|
-
const totalTimeMin = (totalAh / draw) * 60;
|
|
114
|
-
|
|
115
|
-
const energyWh = (cap / 1000) * voltage;
|
|
116
|
-
|
|
117
|
-
renderResults(safeTimeMin, totalTimeMin, energyWh, cap);
|
|
118
|
-
updateChart(usableAh);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function updateDisplays(state: { cap: number; cells: number; safety: number; draw: number; voltage: number }) {
|
|
122
|
-
if (displays.cap) displays.cap.textContent = state.cap.toString();
|
|
123
|
-
if (displays.cells) displays.cells.textContent = state.cells.toString();
|
|
124
|
-
if (displays.volts) displays.volts.textContent = state.voltage.toFixed(1);
|
|
125
|
-
if (displays.safety) displays.safety.textContent = Math.round(state.safety * 100).toString();
|
|
126
|
-
if (displays.draw) displays.draw.textContent = state.draw.toFixed(1);
|
|
127
|
-
if (displays.watts) displays.watts.textContent = (state.draw * state.voltage).toFixed(1);
|
|
128
|
-
if (displays.eff) displays.eff.textContent = effInput.value;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function renderResults(safeMin: number, totalMin: number, wh: number, cap: number) {
|
|
132
|
-
if (displays.timeMain) displays.timeMain.textContent = formatTime(safeMin);
|
|
133
|
-
if (displays.timeTotal) displays.timeTotal.textContent = formatTime(totalMin);
|
|
134
|
-
if (displays.wh) displays.wh.textContent = `${wh.toFixed(1)} Wh`;
|
|
135
|
-
if (displays.co2) displays.co2.textContent = `${Math.round(cap * 0.05)} g`;
|
|
136
|
-
|
|
137
|
-
if (displays.circle) {
|
|
138
|
-
const limit = 20;
|
|
139
|
-
const progress = Math.min(safeMin / limit, 1);
|
|
140
|
-
const offset = 283 - (progress * 283);
|
|
141
|
-
(displays.circle as HTMLElement).style.strokeDashoffset = offset.toString();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function formatTime(decimalMin: number) {
|
|
146
|
-
if (isNaN(decimalMin) || decimalMin === Infinity) return "0:00";
|
|
147
|
-
const mins = Math.floor(decimalMin);
|
|
148
|
-
const secs = Math.floor((decimalMin - mins) * 60);
|
|
149
|
-
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function updateChart(usableAh: number) {
|
|
153
|
-
if (!chart) return;
|
|
154
|
-
const data: number[] = [];
|
|
155
|
-
const labels: string[] = [];
|
|
156
|
-
const currentDraw = parseFloat(drawInput.value);
|
|
157
|
-
|
|
158
|
-
for (let a = Math.max(1, currentDraw - 20); a <= currentDraw + 20; a += 2) {
|
|
159
|
-
labels.push(`${a}A`);
|
|
160
|
-
const val = ((usableAh / a) * 60);
|
|
161
|
-
data.push(Number(val.toFixed(1)));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
chart.data.labels = labels;
|
|
165
|
-
if (chart.data.datasets[0]) chart.data.datasets[0].data = data;
|
|
166
|
-
chart.update('none');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
[capInput, cellsInput, safetyInput, drawInput, effInput].forEach(el => {
|
|
170
|
-
el?.addEventListener("input", () => calculate('basic'));
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
wattsInput?.addEventListener("input", () => calculate('watts'));
|
|
174
|
-
|
|
175
|
-
document.querySelectorAll('.preset-btn').forEach(btn => {
|
|
176
|
-
btn.addEventListener('click', () => {
|
|
177
|
-
capInput.value = btn.getAttribute('data-val') || "1500";
|
|
178
|
-
calculate('basic');
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
initChart();
|
|
183
|
-
calculate('basic');
|
|
184
|
-
</script>
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
1
|
+
---
|
|
2
|
+
const { ui } = Astro.props;
|
|
3
|
+
import BatterySpecs from "./components/BatterySpecs.astro";
|
|
4
|
+
import ConsumptionStats from "./components/ConsumptionStats.astro";
|
|
5
|
+
import FlightDashboard from "./components/FlightDashboard.astro";
|
|
6
|
+
import AutonomyChart from "./components/AutonomyChart.astro";
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<div class="flight-calculator-ui">
|
|
10
|
+
<div class="tech-mega-card animate-in fade-in zoom-in duration-700">
|
|
11
|
+
<div class="card-grid">
|
|
12
|
+
<div class="config-sidebar">
|
|
13
|
+
<BatterySpecs ui={ui} />
|
|
14
|
+
<div class="divider"></div>
|
|
15
|
+
<ConsumptionStats ui={ui} />
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="main-display">
|
|
19
|
+
<FlightDashboard ui={ui} />
|
|
20
|
+
<div class="divider"></div>
|
|
21
|
+
<AutonomyChart ui={ui} />
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
import { Chart, registerables } from "chart.js";
|
|
29
|
+
Chart.register(...registerables);
|
|
30
|
+
|
|
31
|
+
const capInput = document.getElementById("capacityInput") as HTMLInputElement;
|
|
32
|
+
const cellsInput = document.getElementById("cellsInput") as HTMLSelectElement;
|
|
33
|
+
const safetyInput = document.getElementById("safetyInput") as HTMLInputElement;
|
|
34
|
+
const drawInput = document.getElementById("drawInput") as HTMLInputElement;
|
|
35
|
+
const wattsInput = document.getElementById("wattsInput") as HTMLInputElement;
|
|
36
|
+
const effInput = document.getElementById("efficiencyInput") as HTMLInputElement;
|
|
37
|
+
|
|
38
|
+
const displays = {
|
|
39
|
+
cap: document.getElementById("capDisplay"),
|
|
40
|
+
cells: document.getElementById("cellsDisplay"),
|
|
41
|
+
volts: document.getElementById("voltsDisplay"),
|
|
42
|
+
safety: document.getElementById("safetyDisplay"),
|
|
43
|
+
draw: document.getElementById("drawDisplay"),
|
|
44
|
+
watts: document.getElementById("wattsDisplay"),
|
|
45
|
+
eff: document.getElementById("effDisplay"),
|
|
46
|
+
timeMain: document.getElementById("timeMainDisplay"),
|
|
47
|
+
timeTotal: document.getElementById("timeTotalDisplay"),
|
|
48
|
+
wh: document.getElementById("whDisplay"),
|
|
49
|
+
co2: document.getElementById("co2Display"),
|
|
50
|
+
circle: document.getElementById("timeCircle")
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
let chart: Chart | null = null;
|
|
54
|
+
|
|
55
|
+
function getChartConfig(label: string) {
|
|
56
|
+
return {
|
|
57
|
+
type: "line",
|
|
58
|
+
data: {
|
|
59
|
+
labels: [],
|
|
60
|
+
datasets: [{
|
|
61
|
+
label,
|
|
62
|
+
data: [],
|
|
63
|
+
borderColor: "#f59e0b",
|
|
64
|
+
backgroundColor: "rgba(245, 158, 11, 0.1)",
|
|
65
|
+
borderWidth: 3,
|
|
66
|
+
fill: true,
|
|
67
|
+
tension: 0.4,
|
|
68
|
+
pointRadius: 0,
|
|
69
|
+
pointHitRadius: 10
|
|
70
|
+
}]
|
|
71
|
+
},
|
|
72
|
+
options: {
|
|
73
|
+
responsive: true,
|
|
74
|
+
maintainAspectRatio: false,
|
|
75
|
+
plugins: { legend: { display: false } },
|
|
76
|
+
scales: {
|
|
77
|
+
y: { beginAtZero: true, grid: { color: "rgba(0,0,0,0.05)" } },
|
|
78
|
+
x: { grid: { display: false } }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function initChart() {
|
|
85
|
+
const canvas = document.getElementById("autonomyChart") as HTMLCanvasElement;
|
|
86
|
+
const ctx = canvas?.getContext("2d");
|
|
87
|
+
if (!ctx) return;
|
|
88
|
+
const chartLabel = canvas.dataset.label || "Minutos";
|
|
89
|
+
chart = new Chart(ctx, getChartConfig(chartLabel));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function calculate(source: string) {
|
|
93
|
+
const cap = parseFloat(capInput.value);
|
|
94
|
+
const cells = parseInt(cellsInput.value);
|
|
95
|
+
const safety = parseFloat(safetyInput.value) / 100;
|
|
96
|
+
let draw = parseFloat(drawInput.value);
|
|
97
|
+
const voltage = cells * 3.7;
|
|
98
|
+
|
|
99
|
+
if (source === 'watts') {
|
|
100
|
+
draw = parseFloat(wattsInput.value) / voltage;
|
|
101
|
+
drawInput.value = draw.toFixed(1);
|
|
102
|
+
} else {
|
|
103
|
+
wattsInput.value = (draw * voltage).toFixed(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const state = { cap, cells, safety, draw, voltage };
|
|
107
|
+
updateDisplays(state);
|
|
108
|
+
|
|
109
|
+
const usableAh = (cap / 1000) * safety;
|
|
110
|
+
const totalAh = cap / 1000;
|
|
111
|
+
|
|
112
|
+
const safeTimeMin = (usableAh / draw) * 60;
|
|
113
|
+
const totalTimeMin = (totalAh / draw) * 60;
|
|
114
|
+
|
|
115
|
+
const energyWh = (cap / 1000) * voltage;
|
|
116
|
+
|
|
117
|
+
renderResults(safeTimeMin, totalTimeMin, energyWh, cap);
|
|
118
|
+
updateChart(usableAh);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function updateDisplays(state: { cap: number; cells: number; safety: number; draw: number; voltage: number }) {
|
|
122
|
+
if (displays.cap) displays.cap.textContent = state.cap.toString();
|
|
123
|
+
if (displays.cells) displays.cells.textContent = state.cells.toString();
|
|
124
|
+
if (displays.volts) displays.volts.textContent = state.voltage.toFixed(1);
|
|
125
|
+
if (displays.safety) displays.safety.textContent = Math.round(state.safety * 100).toString();
|
|
126
|
+
if (displays.draw) displays.draw.textContent = state.draw.toFixed(1);
|
|
127
|
+
if (displays.watts) displays.watts.textContent = (state.draw * state.voltage).toFixed(1);
|
|
128
|
+
if (displays.eff) displays.eff.textContent = effInput.value;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function renderResults(safeMin: number, totalMin: number, wh: number, cap: number) {
|
|
132
|
+
if (displays.timeMain) displays.timeMain.textContent = formatTime(safeMin);
|
|
133
|
+
if (displays.timeTotal) displays.timeTotal.textContent = formatTime(totalMin);
|
|
134
|
+
if (displays.wh) displays.wh.textContent = `${wh.toFixed(1)} Wh`;
|
|
135
|
+
if (displays.co2) displays.co2.textContent = `${Math.round(cap * 0.05)} g`;
|
|
136
|
+
|
|
137
|
+
if (displays.circle) {
|
|
138
|
+
const limit = 20;
|
|
139
|
+
const progress = Math.min(safeMin / limit, 1);
|
|
140
|
+
const offset = 283 - (progress * 283);
|
|
141
|
+
(displays.circle as HTMLElement).style.strokeDashoffset = offset.toString();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function formatTime(decimalMin: number) {
|
|
146
|
+
if (isNaN(decimalMin) || decimalMin === Infinity) return "0:00";
|
|
147
|
+
const mins = Math.floor(decimalMin);
|
|
148
|
+
const secs = Math.floor((decimalMin - mins) * 60);
|
|
149
|
+
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function updateChart(usableAh: number) {
|
|
153
|
+
if (!chart) return;
|
|
154
|
+
const data: number[] = [];
|
|
155
|
+
const labels: string[] = [];
|
|
156
|
+
const currentDraw = parseFloat(drawInput.value);
|
|
157
|
+
|
|
158
|
+
for (let a = Math.max(1, currentDraw - 20); a <= currentDraw + 20; a += 2) {
|
|
159
|
+
labels.push(`${a}A`);
|
|
160
|
+
const val = ((usableAh / a) * 60);
|
|
161
|
+
data.push(Number(val.toFixed(1)));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
chart.data.labels = labels;
|
|
165
|
+
if (chart.data.datasets[0]) chart.data.datasets[0].data = data;
|
|
166
|
+
chart.update('none');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
[capInput, cellsInput, safetyInput, drawInput, effInput].forEach(el => {
|
|
170
|
+
el?.addEventListener("input", () => calculate('basic'));
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
wattsInput?.addEventListener("input", () => calculate('watts'));
|
|
174
|
+
|
|
175
|
+
document.querySelectorAll('.preset-btn').forEach(btn => {
|
|
176
|
+
btn.addEventListener('click', () => {
|
|
177
|
+
capInput.value = btn.getAttribute('data-val') || "1500";
|
|
178
|
+
calculate('basic');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
initChart();
|
|
183
|
+
calculate('basic');
|
|
184
|
+
</script>
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
---
|
|
2
|
-
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
-
import { droneFlightTime } from './index';
|
|
4
|
-
import type { KnownLocale } from '../../types';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
locale?: KnownLocale;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const { locale = 'es' } = Astro.props;
|
|
11
|
-
const content = await droneFlightTime.i18n[locale]?.();
|
|
12
|
-
if (!content) return null;
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { droneFlightTime } from './index';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'es' } = Astro.props;
|
|
11
|
+
const content = await droneFlightTime.i18n[locale]?.();
|
|
12
|
+
if (!content) return null;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type { SEOSection } from '../../types';
|
|
3
2
|
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import type { KnownLocale } from '../../types';
|
|
4
|
+
import { droneMotorPropellerCalculator } from './entry';
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
6
|
-
|
|
7
|
+
locale?: KnownLocale;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
const {
|
|
10
|
+
const { locale = 'es' } = Astro.props;
|
|
11
|
+
const content = await droneMotorPropellerCalculator.i18n[locale]?.();
|
|
12
|
+
if (!content) return null;
|
|
10
13
|
---
|
|
11
14
|
|
|
12
|
-
<SEORenderer content={{ locale
|
|
15
|
+
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|