HEX
Server: nginx/1.18.0
System: Linux test-ipsremont 5.4.0-214-generic #234-Ubuntu SMP Fri Mar 14 23:50:27 UTC 2025 x86_64
User: ips (1000)
PHP: 8.0.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
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>