Skip to content

Commit

Permalink
Merge pull request #342 from significa/fix-estimations
Browse files Browse the repository at this point in the history
Fix estimations
  • Loading branch information
kaaps authored Mar 5, 2024
2 parents ca70a64 + 2ebfc6f commit 8c1e7fe
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 127 deletions.
27 changes: 19 additions & 8 deletions components.198185.json
Original file line number Diff line number Diff line change
Expand Up @@ -2247,31 +2247,40 @@
"name": "landing-page",
"display_name": null,
"created_at": "2024-01-09T16:40:58.537Z",
"updated_at": "2024-01-16T10:35:21.911Z",
"updated_at": "2024-02-29T15:42:02.200Z",
"id": 5142044,
"schema": {
"keep_top_bar_hidden": {
"type": "boolean",
"pos": 0,
"required": false
},
"blocks": {
"type": "bloks",
"restrict_type": "groups",
"restrict_components": true,
"component_whitelist": [],
"component_group_whitelist": ["c9011224-9690-43bd-b686-e8f60ef6c7f6"]
"component_group_whitelist": ["c9011224-9690-43bd-b686-e8f60ef6c7f6"],
"pos": 1
},
"tab-577daf7c-b61e-4a23-8184-bd9c01ae0af3": {
"display_name": "SEO",
"keys": ["seo_title", "seo_description", "seo_og_image", "change_frequency", "priority"],
"pos": 0,
"pos": 2,
"type": "tab"
},
"seo_title": {
"type": "text"
"type": "text",
"pos": 3
},
"seo_description": {
"type": "text"
"type": "text",
"pos": 4
},
"seo_og_image": {
"type": "asset",
"filetypes": ["images"]
"filetypes": ["images"],
"pos": 5
},
"change_frequency": {
"type": "option",
Expand Down Expand Up @@ -2313,12 +2322,14 @@
"value": "never",
"name": "Never"
}
]
],
"pos": 6
},
"priority": {
"type": "number",
"description": "The priority of the page relative to other pages on your site, where 0.1 is the lowest priority and 1.0 is the highest priority.\n\n1.0-0.8\nHomepage, product information, landing pages.\n\n0.7-0.4\nNews articles, some weather services, blog posts, pages that no site would be complete without.\n\n0.3-0.0\nFAQs, outdated info, old press releases, completely static pages that are still relevant enough to keep from deleting entirely.",
"decimals": 1
"decimals": 1,
"pos": 7
}
},
"image": null,
Expand Down
249 changes: 151 additions & 98 deletions src/components/blocks/estimation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,58 @@
import type { EstimationStoryblok } from '$types/bloks';
import IllustrationEmply from '../illustrations/assets/illustration-emply.webp';
import IllustrationEmplyLight from '../illustrations/assets/illustration-emply-light.webp';
import ArrowLight from '../illustrations/assets/arrow-estimations-white.webp';
import ArrowDark from '../illustrations/assets/arrow-estimations.webp';
import { theme } from '$lib/stores/theme';
import { Icon, MultiSelect } from '@significa/svelte-ui';
import { CheckboxGroup, Radio } from '@significa/svelte-ui';
import clsx from 'clsx';
import ContactForm from '$components/contact-form.svelte';
import { estimations } from '$lib/estimations';
import type { ListboxOption } from '@melt-ui/svelte/dist/builders/listbox/types';
import { estimations, estimationsCheckbox } from '$lib/estimations';
import HandAsset from '../illustrations/assets/hand.webp';
import PreFooterAsset from '../illustrations/assets/pre-footer.webp';
import PreFooterAssetLight from '../illustrations/assets/pre-footer-light.webp';
import { t } from '$lib/i18n';
export let block: EstimationStoryblok;
let open = false;
$: src = $theme === 'dark' ? IllustrationEmply : IllustrationEmplyLight;
$: srcArrow = $theme === 'dark' ? ArrowDark : ArrowLight;
let selected: Record<string, ListboxOption<string>[]> = {};
let selectedRadio: Array<string> = [];
let selectedCheckbox: Array<string> = [];
$: selectedMap = Object.entries(selected).map(([key, value]) => ({ key, value }));
$: selectedValuesToNotion = [
...estimations.flatMap((estimation, index) =>
estimation.options
.filter((option) => option.name === selectedRadio[index])
.map((option) => `${estimation.name} / ${option.name}`)
),
...estimationsCheckbox.flatMap((estimation) =>
estimation.options
.filter((option) => selectedCheckbox.includes(option.name))
.map((option) => `${estimation.name} / ${option.name}`)
)
].join(' , ');
$: selectedKeyValues = selectedMap.map(({ value }) => value.map((v) => v.value)).flat();
$: estimationsMapRadio = estimations
.map((v, i) => v.options.filter((o) => o.name === selectedRadio[i]))
.flat();
let estimationsMap = estimations.map((v) => v.options.filter((o) => o.name)).flat();
$: estimationsMapCheckbox = estimationsCheckbox
.map((v) => v.options.filter((v) => selectedCheckbox.includes(v.name)))
.flat();
$: combinedBudgetPower = estimationsMap
.filter((r) => selectedKeyValues.includes(r.name))
.reduce(
(a, b) => {
return {
lowBudget: a.lowBudget + Number(b['low-bud-point']),
highBudget: a.highBudget + Number(b['high-bud-point']),
lowPower: a.lowPower + Number(b['low-est-point']),
highPower: a.highPower + Number(b['high-est-point'])
};
},
{ lowBudget: 0, highBudget: 0, lowPower: 0, highPower: 0 }
);
$: combinedBudgetPower = [...estimationsMapRadio, ...estimationsMapCheckbox].reduce(
(a, b) => {
return {
lowBudget: a.lowBudget + Number(b['low-est-point']) * 14500,
highBudget: a.highBudget + Number(b['high-est-point']) * 14500,
lowPower: a.lowPower + Number(b['low-est-point']),
highPower: a.highPower + Number(b['high-est-point'])
};
},
{ lowBudget: 0, highBudget: 0, lowPower: 0, highPower: 0 }
);
// open / close form
$: Object.values(combinedBudgetPower).every((val) => val !== 0) ? (open = true) : (open = false);
$: open = Object.values(combinedBudgetPower).every((val) => val !== 0);
</script>

<section class="border-t mt-20" id="estimation">
Expand All @@ -58,92 +66,130 @@
</div>
</section>

<section class="container mx-auto px-container @container pt-20 pb-16 flex">
<section class="container mx-auto xl:px-container @container pt-20 pb-16 flex">
<div
class="rounded-lg border w-full overflow-hidden flex min-h-[unset] xl:min-h-[710px] flex-col xl:flex-row relative"
class="rounded-lg xl:border w-full xl:overflow-hidden flex min-h-[unset] flex-col xl:flex-row relative"
>
<img
class={clsx(
'absolute right-1/2 hidden xl:block transition-all ease-motion duration-500',
!open ? '-bottom-96 opacity-0 select-none' : 'bottom-0 opacity-100'
)}
src={$theme === 'dark' ? PreFooterAsset : PreFooterAssetLight}
width="354"
alt=""
/>
<div
class={clsx(
'flex transition-all duration-500 ease-motion bg-background-panel rounded-b-lg xl:rounded-r-lg',
open ? 'xl:w-1/2 w-full ring-1 ring-border' : 'w-full'
'flex transition-all duration-300 ease-motion w-full xl:bg-background-panel xl:rounded-b-lg xl:rounded-r-lg z-50',
open ? 'xl:ring-1 xl:ring-border xl:w-2/3' : 'w-full min-w-full'
)}
>
<div class="w-full @5xl:flex">
<div class="p-6 xl:p-8 flex flex-col justify-between h-full xl:max-w-2xl">
<div>
<div class="block w-full">
<div class="flex flex-col h-full relative z-10">
<div class="order-1 xl:pt-8 xl:px-8 px-container">
<h3 class="text-4xl max-w-md">
{block.title}
</h3>
<p class="my-4 text-xl text-foreground-secondary max-w-md">
{block.description}
</p>
<div class="py-4 xl:py-6 inline-flex lg:flex-row flex-col flex-wrap gap-4 relative">
<img
class={clsx(
'hidden xl:block absolute top-12 -right-4 translate-x-full',
open ? 'xl:hidden xl:opacity-0' : 'opacity-100'
)}
width="164"
src={srcArrow}
alt=""
/>
{#each estimations as { name, options }}
<MultiSelect
options={options.map((o) => o.name)}
bind:selected={selected[name]}
selectedLabel={name}
icon="plus"
class="w-full xs:w-fit"
/>
{/each}
</div>

<div class="flex flex-wrap gap-4 max-w-xl z-10 relative">
{#each selectedMap as option}
{#each option.value as op}
</div>
<div class="xl:order-2 order-3 xl:px-8 px-container">
<div
class={clsx('pb-4 pt-2 xl:pb-8 gap-4 relative w-full', open ? 'w-full' : 'xl:w-2/3')}
>
<div class="flex flex-col md:grid md:grid-cols-2 xl:grid-cols-3 gap-y-4 gap-x-5">
{#each estimations as options, i}
<div class="gap-2 grid">
<div class="grid grid-cols-2 items-center pt-4 pb-2">
<p class="leading-none text-foreground-secondary text-sm">
{options.name}
</p>
<button
class="leading-none text-foreground-tertiary text-sm hover:text-foreground-secondary transition-all flex justify-end"
on:click={() => {
selectedRadio[i] = '';
}}
>
{t('estimate.clear')}
</button>
</div>
<div class="grid grid-cols-2 xl:flex xl:flex-col gap-2">
{#each options.options as opt}
<label
for={`${options.name} / ${opt.name}`}
class={clsx(
'flex flex-col items-start py-2 px-3 transition-all hover:bg-foreground/2 cursor-pointer border rounded-sm hover:border-border-active hover:ring-2 text-sm/[20px] select-none'
)}
>
<div class="flex items-center justify-between w-full">
<p class="font-medium pr-3">{opt.name}</p>
<Radio
class="cursor-pointer shrink-0"
id={`${options.name} / ${opt.name}`}
value={opt.name}
name={options.name}
checked={selectedRadio[i] === opt.name}
bind:group={selectedRadio[i]}
/>
</div>
</label>
{/each}
</div>
</div>
{/each}
{#each estimationsCheckbox as options}
<div
class="flex items-center justify-between px-2.5 py-1.5 border border-border bg-background-offset text-xs font-semibold rounded-xs w-fit hover:transition-all focus-within:border-border-active focus-within:outline-none focus-within:ring-4 focus-within:ring-outline focus-within:transition-all hover:opacity-80"
class="gap-2 grid col-span-2 grid-cols-2 xl:gap-x-5 [&:last-child>p]:col-span-2"
>
{op.label}
<button
class="outline-none flex"
on:click={() => {
let opSelected = selected[option.key].filter(
(value) => value.label !== op.label
);
selected[option.key] = opSelected;
}}
>
<Icon class="ml-2" icon="close" />
</button>
<p class="pt-4 leading-none text-foreground-secondary text-sm grid pb-2">
{options.name}
</p>

{#each options.options as opt}
<label
for={`${options.name} / ${opt.name}`}
class={clsx(
'flex flex-col items-start py-2 px-3 transition-all hover:bg-foreground/2 cursor-pointer border rounded-sm hover:border-border-active hover:ring-2 text-sm/[20px] select-none'
)}
>
<div class="flex items-center justify-between w-full">
<p class="font-medium pr-3">{opt.name}</p>
<CheckboxGroup
bind:group={selectedCheckbox}
id={`${options.name} / ${opt.name}`}
value={opt.name}
name={options.name}
/>
</div>
</label>
{/each}
</div>
{/each}
{/each}
</div>
</div>
</div>

<div class="flex flex-col mt-5 xl:mt-3">
<p class="text-base font-medium text-foreground/60">{t('estimation.man.power')}</p>
<p class="text-xl font-medium">
{combinedBudgetPower.lowPower === 0
? '-'
: combinedBudgetPower.lowPower + ` to ` + combinedBudgetPower.highPower}
</p>
<p class="text-base font-medium text-foreground/60 mt-6">{t('estimation.total')}</p>
<p class="text-xl font-medium text-foreground-accent">
{combinedBudgetPower.lowBudget === 0
? '-'
: combinedBudgetPower.lowBudget + `€ to ` + combinedBudgetPower.highBudget + ``}
</p>
<div
class="flex flex-col mt-2 xl:mt-3 mb-4 xl:mb-0 sticky top-0 xl:relative xl:top-auto order-2 xl:order-3 z-10 border-b xl:border-none w-screen xl:w-full bg-background xl:bg-transparent xl:pb-8 xl:px-8"
>
<div class="py-3 px-container xl:py-0 xl:px-0 flex xl:block gap-2 xl:gap-0">
<div class="w-1/2 xl:w-auto">
<p class="text-base/5 xl:text-base font-medium text-foreground/60">
{t('estimation.man.power')}
</p>
<p class="text-md md:text-xl font-medium">
{combinedBudgetPower.lowPower === 0
? '-'
: combinedBudgetPower.lowPower + ` to ` + combinedBudgetPower.highPower}
</p>
</div>
<div class="w-1/2 xl:w-auto">
<p class="text-base/5 xl:text-base font-medium text-foreground/60 mt-0 xl:mt-6">
{t('estimation.total')}
</p>
<p class="text-md xl:text-xl font-medium text-foreground-accent">
{combinedBudgetPower.lowBudget === 0
? '-'
: combinedBudgetPower.lowBudget +
`€ to ` +
combinedBudgetPower.highBudget +
``}
</p>
</div>
</div>
</div>
</div>
<div
Expand All @@ -152,11 +198,18 @@
open ? 'xl:hidden xl:opacity-0' : 'right-0 opacity-100'
)}
>
<img class="max-w-[710px]" {src} alt="" />
<img class="max-w-[710px] pointer-events-none" {src} alt="" />
</div>
</div>
</div>
<div class={clsx('xl:w-1/2 w-full p-8', open ? 'flex flex-col justify-between' : 'hidden')}>
<div
class={clsx(
'pt-8 xl:p-8 transition-all duration-300 w-full xl:w-auto z-10 px-container',
open
? 'flex flex-col justify-between flex-0.5 shrink-0 translate-y-0 xl:translate-x-0 xl:w-1/3 xl:translate-y-0'
: '-translate-y-full xl:translate-x-full xl:translate-y-0 hidden xl:flex'
)}
>
<div>
<h3 class="text-4xl max-w-[300px]">
{block.form_title}
Expand All @@ -167,7 +220,7 @@
</div>
<ContactForm variant="estimations">
<svelte:fragment slot="estimationsform">
<input name="estimations" hidden bind:value={selectedKeyValues} />
<input name="estimations" hidden bind:value={selectedValuesToNotion} />
</svelte:fragment>
</ContactForm>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/blocks/work-recognitions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

<div style="background-image: url({src});">
<section
class="container mx-auto px-container @container flex flex-col max-w-[1056px] pt-32 relative"
class="container mx-auto px-container @container flex flex-col max-w-[1056px] pt-16 xl:pt-32 relative"
>
<img src={EggChicken} class="absolute block drop-shadow-md -right-56 -bottom-80" alt="" />
<img src={QuimHead} class="absolute block drop-shadow-md -left-60 top-12" alt="" />
Expand Down
Loading

0 comments on commit 8c1e7fe

Please sign in to comment.