File: /var/www/quadcode.com/builds/-DFbjr9L/0/foach/quadcode.com/src/components/blocks/blog/Aside.svelte
<script lang="ts">
import Share from './Share.svelte';
import type { IPost } from '../../../type/post';
import type { IForm } from '../../../type/form';
import { browser } from '$app/environment';
import Validation from '../../../utils/Validation';
import createEvent from '../../../utils/createEvents';
import Button from '../../button/Button.svelte';
if (browser) {
const urlParams = new URLSearchParams(window.location.search);
const entries = urlParams.entries();
for (const entry of entries) {
localStorage.setItem('param__' + entry[0], entry[1]);
}
}
export let className: string | undefined = '';
export let data: IPost;
const formState: IForm = {
loading: false,
error: false,
data: {
email: '',
},
response: {},
status: 0,
};
const sendForm = async () => {
formState.loading = true;
for (let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
if (key && key.includes('param__')) {
formState.data[key.replace('param__', '')] = localStorage.getItem(key) || null;
}
}
formState.data['landing_url'] = window.location.host + window.location.pathname;
formState.data['language'] = document.documentElement.lang;
for (const [key, value] of Object.entries(formState.data)) {
Validation({ name: key, value: value, formState });
}
if (Object.values(formState.response).length) {
formState.loading = false;
return;
}
createEvent({ event: 'saas_form_sent' });
await fetch(`/api/send/email`, {
method: 'POST',
body: JSON.stringify({
...formState.data,
isPost: true,
}),
})
.then((response) => {
formState.status = response.status;
return response.json();
})
.then((response) => {
formState.response = response;
})
.finally(() => {
formState.loading = false;
if (formState.response.status === 'ok') {
formState.data = {};
formState.response = {};
formState.status = 0;
}
});
};
</script>
<aside class="aside {className}">
<Share className="aside__share right" />
{#if data.readAlso.length}
<div class="aside__also">
<p class="aside__alsoTitle">Read also</p>
<div class="aside__alsoItems">
{#each data.readAlso as post}
<div class="aside__alsoItem" style="border-top: 2px solid {post?.color ? post?.color : 'white'}">
<a href="/blog/{post.slug}">{post.title}</a>
</div>
{/each}
</div>
</div>
{/if}
<div class="aside__subscribe">
<p class="aside__subscribeTitle">Subscribe to our newsletter</p>
<p class="aside__subscribeText">We send out weekly newsletter with the best marketing tips.</p>
<input
class="aside__subscribeInput"
id="email"
value={formState.data.email ?? ''}
name="email"
placeholder="Your email"
type="email"
on:input={(e) => {
formState.data.email = e.currentTarget.value;
Validation({ name: 'email', value: e.currentTarget.value, formState });
}}
/>
{#if formState.response.email}
<p class="aside__subscribeInputError">{formState.response.email}</p>
{/if}
<Button text="Subscribe" onClick={sendForm} className="aside__subscribeButton" loading={formState.loading} />
</div>
</aside>
<style lang="scss">
@import 'src/scss/media';
@import 'src/scss/mixins';
@import 'src/scss/variables';
.aside {
& :global(.aside__share) {
margin-bottom: 56px;
@include breakpoint-down('deskL') {
margin-bottom: 69px;
}
@include breakpoint-down('deskS') {
display: none;
}
}
&__also {
margin-bottom: 60px;
@include breakpoint-down('deskL') {
margin-bottom: 68px;
}
}
&__alsoTitle {
@include baseTitle;
margin-bottom: 40px;
@include breakpoint-down('deskL') {
margin-bottom: 28px;
}
@include breakpoint-down('deskS') {
margin-bottom: 22px;
}
}
&__alsoItems {
width: 100%;
}
&__alsoItem {
@include smallCTA;
margin-bottom: 16px;
border-radius: 0 0 8px 8px;
background: $techWhite;
@include breakpoint-down('deskL') {
margin-bottom: 14px;
}
> a {
display: flex;
width: 100%;
padding: 24px;
@include breakpoint-down('deskL') {
padding: 24px 20px;
}
@include breakpoint-down('deskS') {
padding: 24px 8px;
}
}
&:last-of-type {
margin-bottom: 0;
}
}
&__subscribe {
border-radius: 16px;
background: linear-gradient(180deg, #eef3f6 0%, #f1f3f4 100%);
display: flex;
padding: 24px;
flex-direction: column;
gap: 16px;
position: sticky;
top: 127px;
@include breakpoint-down('deskL') {
top: 118px;
}
@include breakpoint-down('deskS') {
display: none;
}
}
&__subscribeTitle {
@include baseTitle;
color: $techBluePrimary;
}
&__subscribeText {
@include smallDefault;
color: $techBlueSecondary;
}
&__subscribeInput {
@include smallDefault;
outline: none;
padding: 14px 24px;
border-radius: 40px;
border: 1px solid $techBlueSecondary;
background: $techWhite;
width: 100%;
&::placeholder {
color: $techBlueSecondary;
}
}
&__subscribeInputError {
font-size: 12px;
font-weight: 400;
line-height: 14px;
color: $redPrimary;
margin-top: -14px;
}
:global(.aside__subscribeButton) {
@include blogBaseCTA;
border-radius: 40px;
background: $techBluePrimary;
color: $techWhite;
padding: 10px 50px;
width: 100%;
cursor: pointer;
}
}
</style>