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/src/components/form/Form.svelte
<script lang="ts">
import Validation from '$utils/Validation';
import { localeLink } from '$lib/translations';
import InputField from './input/InputField.svelte';
import TextareaField from './input/TextareaField.svelte';
import CheckboxField from './input/CheckboxField.svelte';
import Message from './message/Message.svelte';
import InputFieldPhone from './input/InputFieldPhone.svelte';
import Button from '../button/Button.svelte';
import { browser } from '$app/environment';
import type { IForm } from '$type/form';
import createEvent from '$utils/createEvents';
import { env } from '$env/dynamic/public';
import { t } from '$lib/translations'
import logoImage from '../../assets/logo-short-black.svg';
import { getCookieByName } from '$utils/cookie';

export let logo = false;
export let formTitle = '';
export let formDescription = '';

let roistatId = null;

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]);
  }

  roistatId = getCookieByName('roistat_visit', document.cookie);
}

const formState: IForm = {
  loading: false,
  error: false,
  data: {
    first_name: '',
    email: '',
    tg: '',
    phone: '',
    message: '',
    terms_agree: false,
    roistatId,
  },
  response: {},
  status: 0,
};

const sendForm = async () => {
  formState.loading = true;

  const code = document.querySelector('.iti__selected-dial-code');
  const token = document.querySelector('.g-recaptcha-response');

  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;
    }
  }

  if (code) {
    formState.data.code = code.innerHTML;
  }

  let phone = formState.data.phone;

  if (phone) {
    if (String(phone).includes(String(formState.data.code))) {
      phone = formState.data.phone;
    } else {
      phone = String(formState.data.code) + String(formState.data.phone);
    }
    delete formState.data.code;
  }

  if (token) {
    formState.data.token = token?.value;
  }

  formState.data['landing_url'] = window.location.host + window.location.pathname;
  formState.data['referrer'] = window.location.href;
  formState.data['language'] = document.documentElement.lang;
  formState.data['lang_by_browser'] = 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/popup`, {
    method: 'POST',
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      ...formState.data,
      phone: String(phone).replace(/[^+\d]/g, ''),
    }),
  })
    .then((response) => {
      formState.status = response.status;
      return response.json();
    })
    .then((response) => {
      formState.response = response;
    })
    .finally(() => {
      formState.loading = false;

      const grecaptcha = window?.grecaptcha;

      if (grecaptcha && grecaptcha?.ready && env?.PUBLIC_RECAPTCHA_SITE_KEY) {
        grecaptcha?.reset();
      }
    });
};
const clickSendMore = () => {
  formState.data = {};
  formState.response = {};
  formState.status = 0;

  const grecaptcha = window?.grecaptcha;

  if (grecaptcha && grecaptcha?.ready && env?.PUBLIC_RECAPTCHA_SITE_KEY) {
    grecaptcha?.reset();
  }
};
</script>

<div class="form__form" >
  {#if logo}
    <img class="form__formLogo" src={logoImage} alt="logo">
  {/if}
  <div class="form__formText">
    <p class="form__formTitle">{formTitle}</p>
    <p class="form__formDescription">{formDescription}</p>
  </div>
  <div class="form__formItems">
    <div class="form__formItem">
      <InputField
        className="bordered"
        placeholder={$t("prop-firm.Name*")}
        name="first_name"
        error={formState.response.first_name}
        value={String(formState.data.first_name || '')}
        onChange={(e) => {
                  formState.data.first_name = e.currentTarget.value;
                 Validation({ name: 'first_name', value: e.currentTarget.value, formState });
                }}
      />
    </div>
    <div class="form__formItem">
      <InputField
        className="bordered"
        placeholder={$t("prop-firm.Email*")}
        name="email"
        error={formState.response.email}
        value={String(formState.data.email || '')}
        onChange={(e) => {
                  formState.data.email = e.currentTarget.value;
                  Validation({ name: 'email', value: e.currentTarget.value, formState });
                }}
      />
    </div>
    <div class="form__formItem">
      <InputFieldPhone
        className="bordered"
        placeholder={$t("prop-firm.Phone number*")}
        name="phone"
        error={formState.response.phone}
        value={String(formState.data.phone || '')}
        onChange={(e) => {
                  formState.data.phone = e.currentTarget.value;
                  Validation({ name: 'phone', value: e.currentTarget.value, formState });
                }}
      />
    </div>
    <div class="form__formItem">
      <InputField
        className="bordered"
        placeholder={$t("prop-firm.TG @username")}
        name="tg"
        error={formState.response.tg}
        value={String(formState.data.tg || '')}
        onChange={(e) => {
                    formState.data.tg = e.currentTarget.value;
                    Validation({ name: 'tg', value: e.currentTarget.value, formState });
                  }}
      />
    </div>
    <div class="form__formItem">
      <TextareaField
        className="bordered"
        placeholder={$t("prop-firm.Comment")}
        name="message"
        error={formState.response.text}
        value={String(formState.data.message || '')}
        onChange={(e) => {
                  formState.data.message = e.currentTarget.value;
                }}
      />
    </div>
    <div class="form__formItem">
      <Button
        text={$t("prop-firm.Get Started")}
        className="form__button"
        onClick={sendForm}
        loading={formState.loading}
      />
    </div>
    <div class="form__formItem">
      <CheckboxField
        placeholder={`${$t("By sticking this checkbox I consent with the")} <a href="${localeLink()}/terms-and-conditions">${$t("terms and conditions")}</a> ${$t('and the')} <a href="${localeLink()}/privacy-policy">${$t('policy of the website')}</a>`}
        name="terms_agree"
        error={formState.response.terms_agree}
        checked={Boolean(formState.data.terms_agree)}
        onChange={(e) => {
             formState.data.agreement = e.currentTarget.checked;
             formState.data.terms_agree = e.currentTarget.checked;
              Validation({ name: 'terms_agree', value: e.currentTarget.checked, formState });
            }}
      />
    </div>
  </div>
  {#if formState.response?.status === 'ok'}
    <Message
      onClick={clickSendMore}
      text={$t("prop-firm.Thank you for your interest! Our team will contact you shortly to discuss the details.")}
    />
  {/if}
  {#if [500, 502, 429].includes(formState.status)}
    <Message
      error={true}
      onClick={clickSendMore}
      text={formState.response.error || formState.response.message || ''}
    />
  {/if}
</div>

<style lang="scss">
  @import 'src/scss/media';
  @import 'src/scss/mixins';
  @import 'src/scss/variables';

  .form {
    &__form {
      background: #FFFFFF;
      display: flex;
      flex-direction: column;
      gap: 16px;
      padding: 52px 48.5px;
      border-radius: 40px;
      justify-content: center;
      align-items: center;
      width: 708px;
      @include breakpoint-down('deskL') {
        width: 492px;
        gap: 29px;
        padding: 33px 20px 32px 20px;
        border-radius: 20px;
      }
      @include breakpoint-down('tabL') {
        width: 346px;
        gap: 22px;
      }
      @include breakpoint-down('tabM') {
        width: 100%;
        padding: 32px 14px 14px 14px;
        gap: 25px;
      }
    }
    &__formText {
      padding-bottom: 24px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      gap: 16px;

      @include breakpoint-down('deskL') {
        gap: 13px;
        padding-bottom: 0;
      }
      @include breakpoint-down('tabL') {
        gap: 6px;
      }
      @include breakpoint-down('tabM') {
        gap: 13px;
      }
    }
    &__formLogo {
      width: 184px;
      height: 32px;

      @include breakpoint-down('tabL') {
        margin-bottom: -4px;
      }
    }
    &__overTitle {
      color: $redPrimary;
      font-size: 20px;
      line-height: 24px;
      font-weight: 700;
      @include breakpoint-down('deskL') {
        font-size: 14px;
        line-height: 15.4px;
      }
      @include breakpoint-down('tabL') {
        font-size: 16px;
        line-height: 22.4px;
      }
      @include breakpoint-down('tabM') {
        line-height: 17.6px;
      }
    }
    &__formTitle {
      @include H2;
      text-align: center;
      @include breakpoint-down('deskL') {
        width: 352px;
      }
      @include breakpoint-down('tabL') {
        width: 251px;
      }
      @include breakpoint-down('tabM') {
        @include H2;
        width: 233px;
      }
    }
    &__formDescription {
      @include body;
      text-align: center;
      padding-inline: 13px;

      @include breakpoint-down('deskL') {
        @include subtext;
        padding: 0;
      }
      @include breakpoint-down('tabL') {
        @include table;
        font-weight: 400;
      }
      @include breakpoint-down('tabM') {
        @include body;
      }
    }
    &__formItems {
      padding-inline: 11.5px;
      @include breakpoint-down('tabM') {
        padding-inline: 0;
      }
    }
    &__formItem {
      margin-bottom: 15px;

      @include breakpoint-down('deskL') {
        margin-bottom: 16px;
      }
      @include breakpoint-down('tabL') {
        margin-bottom: 11px;
      }
      @include breakpoint-down('tabM') {
        margin-bottom: 17px;
      }

      &:last-child {
        margin-bottom: 0;
      }
      :global(.button) {
        width: 100%;
        font-size: 30px;
        line-height: 33px;
        @include breakpoint-down('deskL') {
          font-size: 18px;
          line-height: 19.8px;
        }
        @include breakpoint-down('tabL') {
          height: 54px;
        }
        @include breakpoint-down('tabM') {
          height: 45px;
          font-size: 14px;
          line-height: 15.4px;
        }
      }
      :global(.checkbox .checkboxPlaceholder ) {
        font-size: 21px;
        line-height: 28px;
        @include breakpoint-down('deskL') {
          font-size: 14px;
          line-height: 19.6px;
        }
        @include breakpoint-down('tabL') {
          font-size: 10px;
          line-height: 12px;
        }
        @include breakpoint-down('tabM') {
          font-size: 12px;
          line-height: 14.4px;
        }
      }
      :global(.checkbox .checkboxContainer) {
        align-items: center;
        gap: 25px;
        padding-top: 15px;

        @include breakpoint-down('deskL') {
          padding-top: 12px;
          min-height: 47px;
        }
        @include breakpoint-down('tabL') {
          min-height: 36px;
          padding-top: 9px;
          gap: 22px;
        }
        @include breakpoint-down('tabM') {
          min-height: 55px;
          padding-top: 14px;
          align-items: start;
        }
      }
    }
  }
  :global(.form__form .input .inputInput, body .form__form .textarea.bordered .textareaInput) {
    font-size: 24px;
    line-height: 125%;

    border-radius: 12px !important;
    background: rgba(241, 241, 241, 1) !important;
    @include breakpoint-down('deskL') {
      padding: 14px 68px 8px 24px !important;
      font-size: 18px;
      line-height: 140%;
    }
    @include breakpoint-down('deskS') {
      font-size: 16px;
      line-height: 100%;
    }
    @include breakpoint-down('tabM') {
      padding: 14px 68px 5px 10px !important;
      font-size: 12px;
      line-height: 134% !important;
    }
  }
  :global(.form__form .input .inputPlaceholder, .form__form .textarea.bordered .textareaPlaceholder) {
    font-size: 24px;
    line-height: 125%;

    @include breakpoint-down('deskL') {
      @include body;
      line-height: 140%;
    }
    @include breakpoint-down('deskS') {
      font-size: 16px;
      line-height: 100%;
    }
    @include breakpoint-down('tabM') {
      font-size: 12px;
      line-height: 134%;
    }
  }
  :global(body .form__form .textareaInput, body .form__form .textarea.bordered .textareaInput) {
    height: 100px;
    @include breakpoint-down('tabL') {
      height: 88px;
    }
    @include breakpoint-down('tabM') {
      height: 58px;
    }
  }
  :global(body .form__form .iti .iti__selected-flag) {
    border-radius: 12px;
    gap: 10px;
    padding: 0 16px;
    justify-content: center;
    background: rgba(241, 241, 241, 1) !important;

    @include breakpoint-down('deskL') {
      gap: 7px;
    }
  }
  :global(body .form__form .iti .iti__flag-container) {
    width: 127px !important;

    @include breakpoint-down('deskL') {
      width: 104px !important;
    }

    @include breakpoint-down('tabM') {
      width: 70px !important;
    }
  }
  :global(body .form__form .input.bordered .iti .inputInput) {
    width: calc(100% - 137px) !important;

    @include breakpoint-down('deskL') {
      width: calc(100% - 114px) !important;
    }

    @include breakpoint-down('tabM') {
      width: calc(100% - 80px) !important;
    }
  }
  :global(body .form__form  .input.bordered .iti + .inputPlaceholder) {
    left: 160px !important;

    @include breakpoint-down('deskL') {
      left: 138px !important;
    }

    @include breakpoint-down('tabM') {
      left: 94px !important;
    }
  }
  :global(body .form__form .input.bordered .iti .iti__arrow) {
    display: none;
  }
  :global(body .form__form .iti .iti__selected-dial-code) {
    min-width: fit-content;
    width: fit-content;
  }
  :global(body .form__form .iti .iti__flag) {
    @include breakpoint-down('deskL') {
      transform: scale(0.7);
      margin-left: -5px;
    }
  }
</style>