diff --git a/src/routes/weather/compare/[location]/+page.svelte b/src/routes/weather/compare/[location]/+page.svelte index f92c6b5..e86fe13 100644 --- a/src/routes/weather/compare/[location]/+page.svelte +++ b/src/routes/weather/compare/[location]/+page.svelte @@ -39,7 +39,7 @@ import { useHeroActions } from '../../hero.svelte'; import { defaultParameters, hourly, modelGroups, models as modelOptions } from '../../options'; - import ComparisonSelectionDrawer from './ComparisonSelectionDrawer.svelte'; + import ComparisonSelectionPanel from './ComparisonSelectionPanel.svelte'; import ModelPictogramTimeline from './ModelPictogramTimeline.svelte'; import { cardinalDirection, @@ -60,6 +60,10 @@ const AUTOMATIC_SEAMLESS_MODEL_IDS = new Set( modelGroups.find((group) => group.value === 'automatic_seamless')?.models.map((model) => model.value) ); + const COMPARE_MODEL_GROUPS = [ + ...modelGroups.filter((group) => group.value !== 'automatic_seamless'), + ...modelGroups.filter((group) => group.value === 'automatic_seamless') + ]; // Weather code and total cloud cover form one comparison feature. Cloud cover // remains an auxiliary API field for pictogram shading, not a standalone chart. const COMPARISON_HOURLY = hourly.map((group) => @@ -96,8 +100,6 @@ let isMobile = $state(false); let comparisonPlotInsetLeft = $derived(isMobile ? 92 : 116); let comparisonPlotInsetRight = $derived(isMobile ? 8 : 20); - let selectionDrawerMode = $state<'models' | 'variables' | null>(null); - let params = $state({ ...defaultParameters, hourly: [...STANDARD_COMPARE_VARIABLES], @@ -542,14 +544,8 @@ m.compare_group_upper_air ]; const allHourlyVariables = COMPARISON_HOURLY.flat(); - let selectedModels = $derived( - params.models.flatMap((value) => { - const model = modelOptions.find((candidate) => candidate.value === value); - return model ? [model] : []; - }) - ); - let modelDrawerGroups = $derived( - modelGroups.map((group) => ({ + let modelSelectionGroups = $derived( + COMPARE_MODEL_GROUPS.map((group) => ({ value: group.value, label: group.label, options: group.models.map((model) => ({ @@ -559,17 +555,7 @@ })) })) ); - let selectedVariables = $derived( - params.hourly.flatMap((value) => { - const variable = allHourlyVariables.find((candidate) => candidate.value === value); - return variable ? [variable] : []; - }) - ); - let standardVariablesActive = $derived( - params.hourly.length === STANDARD_COMPARE_VARIABLES.length && - STANDARD_COMPARE_VARIABLES.every((variable) => params.hourly.includes(variable)) - ); - let variableDrawerGroups = $derived( + let variableSelectionGroups = $derived( COMPARISON_HOURLY.map((variables, index) => ({ value: `variables_${index}`, label: variableGroupLabels[index](), @@ -824,8 +810,31 @@ {/if} - -
+
+
+

+ {m.compare_variables_heading()} +

+ + {params.hourly.length}/{allHourlyVariables.length} + +
+ toggleSelection('hourly', value)} + onToggleGroup={(values, select) => toggleGroupSelection('hourly', values, select)} + onApply={applyComparisonSelection} + onRestoreDefaults={restoreStandardVariables} + /> +
+ +

{m.compare_models_heading()}

@@ -840,177 +849,13 @@ {m.compare_many_models_warning({ count: params.models.length })}

{/if} -
-
-
-
-

{m.compare_selected_models()}

- {#if modelsDirty} - - {m.compare_selection_pending()} - - {/if} -
- {#if selectedModels.length > 0} -
- {#each selectedModels as model, index (model.value)} - - {/each} -
- {:else} -

{m.compare_no_models_selected()}

- {/if} -
-
- - {#if modelsDirty} - - {/if} -
-
-
-
- -
-
-

- {m.compare_variables_heading()} -

- - {params.hourly.length}/{allHourlyVariables.length} - -
- -
-
-
- -
-
-

{m.compare_standard_preset()}

- - {variablesDirty - ? m.compare_variables_pending() - : standardVariablesActive - ? m.compare_preset_active() - : m.compare_custom_selection({ count: params.hourly.length })} - -
-

- {m.compare_standard_preset_description()} -

- {#if selectedVariables.length > 0} -

- {selectedVariables.map((variable) => variableLabel(variable.value)).join(' · ')} -

- {/if} -
-
-
- {#if !standardVariablesActive} - - {/if} - - {#if variablesDirty} - - {/if} -
-
-
-
- -{#if selectionDrawerMode === 'models'} - toggleSelection('models', value)} onToggleGroup={(values, select) => toggleGroupSelection('models', values, select)} onApply={applyComparisonSelection} - onClose={() => (selectionDrawerMode = null)} /> -{:else if selectionDrawerMode === 'variables'} - toggleSelection('hourly', value)} - onToggleGroup={(values, select) => toggleGroupSelection('hourly', values, select)} - onApply={applyComparisonSelection} - onClose={() => (selectionDrawerMode = null)} - onRestoreDefaults={restoreStandardVariables} - /> -{/if} +
diff --git a/src/routes/weather/compare/[location]/ComparisonSelectionDrawer.svelte b/src/routes/weather/compare/[location]/ComparisonSelectionDrawer.svelte deleted file mode 100644 index f4e629e..0000000 --- a/src/routes/weather/compare/[location]/ComparisonSelectionDrawer.svelte +++ /dev/null @@ -1,233 +0,0 @@ - - - !nextOpen && onClose()}> - -
-
-
- - {mode === 'models' ? m.compare_edit_models() : m.compare_edit_variables()} - - - {mode === 'models' - ? m.compare_edit_models_description() - : m.compare_edit_variables_description()} - -
- -
- -
- -
- - -
-
-
- -
- {#if visibleGroups.length > 0} -
- {#each visibleGroups as visibleGroup (visibleGroup.value)} - {@const fullGroup = groups.find((group) => group.value === visibleGroup.value) ?? visibleGroup} - {@const selection = groupSelection(fullGroup)} -
-
- - onToggleGroup( - fullGroup.options.map((option) => option.value), - !selection.all - )} - /> - - - {selection.count}/{fullGroup.options.length} - - -
-
- {#each visibleGroup.options as option (option.value)} -
- onToggle(option.value)} - /> - -
- {/each} -
-
- {/each} -
- {:else} -
- {m.compare_no_matching_options()} -
- {/if} -
- - -
-
diff --git a/src/routes/weather/compare/[location]/ComparisonSelectionPanel.svelte b/src/routes/weather/compare/[location]/ComparisonSelectionPanel.svelte new file mode 100644 index 0000000..8b660da --- /dev/null +++ b/src/routes/weather/compare/[location]/ComparisonSelectionPanel.svelte @@ -0,0 +1,190 @@ + + +
+
+
+ +
+ + +
+
+
+ +
+ {#if visibleGroups.length > 0} +
+ {#each visibleGroups as visibleGroup (visibleGroup.value)} + {@const fullGroup = + groups.find((group) => group.value === visibleGroup.value) ?? visibleGroup} + {@const selection = groupSelection(fullGroup)} +
+
+ + onToggleGroup( + fullGroup.options.map((option) => option.value), + !selection.all + )} + /> + + + {selection.count}/{fullGroup.options.length} + + +
+
+ {#each visibleGroup.options as option (option.value)} +
+ onToggle(option.value)} + /> + +
+ {/each} +
+
+ {/each} +
+ {:else} +
+ {m.compare_no_matching_options()} +
+ {/if} +
+ +
+
+ {#if mode === 'variables' && onRestoreDefaults} + + {/if} +
+ +
+