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/blocks/investment-calculator/Calculator.svelte
<script lang="ts">
  import { t } from '$lib/translations';
  import { investmentCalculator } from '../../../store';
  import { type IInvestmentCalculator } from '$type/investmentCalculator';
  import CalculatorInput from '$components/blocks/investment-calculator/CalculatorInput.svelte';
  import CalculatorSliderInput from '$components/blocks/investment-calculator/CalculatorSliderInput.svelte';
  import { onMount } from 'svelte';

  let investmentCalculatorData: IInvestmentCalculator;

  investmentCalculator.subscribe((newValue: IInvestmentCalculator): void => {
    investmentCalculatorData = newValue;
  });

  let mode: string = 'basic';

  const toggleMode = (newMode: string) => {
    mode = newMode;
    investmentCalculatorData.mode = newMode;
    investmentCalculator.set(investmentCalculatorData);
    calculate();
  };

  onMount(() => {
    calculate();
  });

  const calculate = () => {
    const {
      initialInvestment,
      timeHorizon: months,
      monthlyContribution,
      returnRate: annualReturn,
      annualInflationRate: annualInflation,
      taxRate,
      investmentFees: annualFeeRate,
      annualContributionIncrease,
    } = investmentCalculatorData;

    if (mode === 'basic') {
      const monthlyReturnRate = (1 + annualReturn / 100) ** (1 / 12) - 1;

      let portfolio = initialInvestment;
      let totalContributions = initialInvestment;
      const chartData = [];

      for (let month = 1; month <= months; month++) {
        portfolio += monthlyContribution;
        totalContributions += monthlyContribution;
        portfolio *= (1 + monthlyReturnRate);

        if (month % 12 === 0) {
          chartData.push({
            year: month / 12,
            totalInvested: Math.ceil(totalContributions),
            totalInterest: Math.ceil(portfolio - totalContributions),
            finalBalance: Math.ceil(portfolio),
          });
        }
      }

      if (months % 12 !== 0) {
        chartData.push({
          year: +(months / 12).toFixed(1),
          totalInvested: Math.ceil(totalContributions),
          totalInterest: Math.ceil(portfolio - totalContributions),
          finalBalance: Math.ceil(portfolio),
        });
      }

      const nominalValue = Math.ceil(portfolio);
      const totalInvested = Math.ceil(totalContributions);
      const totalInterest = Math.ceil(portfolio - totalContributions);
      const finalBalance = nominalValue;

      investmentCalculatorData = {
        ...investmentCalculatorData,
        nominalValue,
        totalInvested,
        totalInterest,
        finalBalance,
        chartData,
      };
      investmentCalculator.set(investmentCalculatorData);
    } else {
      const i = annualInflation / 100;
      const t = taxRate / 100;
      const g = annualContributionIncrease / 100;

      const monthlyReturnRate = (1 + annualReturn / 100) ** (1 / 12) - 1;
      const monthlyFeeRate = (1 + annualFeeRate / 100) ** (1 / 12) - 1;

      let portfolioGross = initialInvestment;
      let portfolioNet = initialInvestment;
      let totalContributions = initialInvestment;
      let currentMonthlyContribution = monthlyContribution;

      for (let month = 1; month <= months; month++) {
        if (month > 1 && (month - 1) % 12 === 0) {
          currentMonthlyContribution *= (1 + g);
        }

        portfolioGross += currentMonthlyContribution;
        portfolioNet += currentMonthlyContribution;
        totalContributions += currentMonthlyContribution;

        portfolioGross *= (1 + monthlyReturnRate);
        portfolioNet *= (1 + monthlyReturnRate) / (1 + monthlyFeeRate);
      }

      const investmentGain = portfolioNet - totalContributions;
      const estimatedTaxes = Math.max(0, investmentGain) * t;
      const afterTaxValue = portfolioNet - estimatedTaxes;
      const inflationFactor = (1 + i) ** (months / 12);

      const nominalValue = Math.ceil(portfolioNet);
      const realValue = Math.ceil(afterTaxValue / inflationFactor);
      const inflationImpact = Math.ceil(portfolioNet - portfolioNet / inflationFactor);
      const managementFees = Math.ceil(portfolioGross - portfolioNet);

      investmentCalculatorData = {
        ...investmentCalculatorData,
        nominalValue,
        realValue,
        estimatedTaxes: Math.ceil(estimatedTaxes),
        inflationImpact,
        managementFees,
      };
      investmentCalculator.set(investmentCalculatorData);
    }
  };
</script>

<div class="block-calculator">
  <div class="container">
    <div class="investmentProfitCalculator__header">
      <h2>{$t('IC.Investment Calculator: Check Your Potential Earnings')}</h2>
      <p>{$t('IC.Use smart investment calculator to see how much your money can grow over time.')}</p>
    </div>
    <div class="investmentProfitCalculator__toggle {mode === 'advanced' ? 'item2' : ''}">
      <button
        class="investmentProfitCalculator__item {mode === 'basic' ? 'active' : ''}"
        on:click={() => toggleMode('basic')}
      >
        {$t('IC.Basic')}
      </button>
      <button
        class="investmentProfitCalculator__item {mode === 'advanced' ? 'active' : ''}"
        on:click={() => toggleMode('advanced')}
      >
        {$t('IC.Advanced')}
      </button>
    </div>
    <div class="investmentProfitCalculator__inputForm {'mode-' + mode}">
      <div class="investmentProfitCalculator__basic">
        <CalculatorInput
          id="initialInvestment"
          title={$t('IC.Initial investment')}
          hint={$t('IC.How much money do you have today?')}
          value="65"
          className="money"
        />
        <CalculatorSliderInput
          id="timeHorizon"
          title={$t('IC.Time horizon')}
          hint={$t('IC.How long are you investing?')}
          value={140}
          range={[0, 250]}
          name={$t('IC.month|months|months')}
        />
        <CalculatorInput
          id="monthlyContribution"
          title={$t('IC.Monthly contribution')}
          hint={$t('IC.How much will you add each month?')}
          value="65"
          className="money"
        />
        <CalculatorSliderInput
          id="returnRate"
          title={$t('IC.Expected annual return')}
          hint={$t('IC.Choose your investment strategy')}
          value={7}
          range={[0, 100]}
          name={$t('%|%|%')}
        />
      </div>
      <div class="investmentProfitCalculator__advanced {mode !== 'advanced' ? 'disabled' : ''}">
        <CalculatorInput
          id="annualInflationRate"
          title={$t('IC.Annual inflation rate')}
          hint={$t('IC.Average price increase per year (usually 2-4%)')}
          value="2"
          className="percent"
        />
        <CalculatorInput
          id="taxRate"
          title={$t('IC.Tax rate')}
          hint={$t('IC.Your estimated tax on investment gains')}
          value="13"
          className="percent"
        />
        <CalculatorInput
          id="investmentFees"
          title={$t('IC.Investment fees %')}
          hint={$t('IC.Annual management fees or expense ratios')}
          value="0.05"
          className="percent"
        />
        <CalculatorInput
          id="annualContributionIncrease"
          title={$t('IC.Annual contribution increase')}
          hint={$t('IC.Percentage by which you will increase your monthly deposit each year.')}
          value="30"
          className="percent"
        />
      </div>
    </div>
    <button
      class="investmentProfitCalculator__calculate"
      on:click={calculate}
    >
      {$t('IC.Calculate')}
    </button>
  </div>
</div>

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

  .block-calculator {

    .container {
      max-width: 1181px;
      padding: 32px;
      background-color: #FFFFFF;
      border-radius: 16px;

      @include breakpoint-down('tabM') {
        border-radius: 32px;
        padding: 20px;
      }
    }

    .investmentProfitCalculator {
      &__header {
        h2 {
          font-weight: 500;
          font-size: 40px;
          line-height: 46px;
          letter-spacing: -3%;

          @include breakpoint-down('tabM') {
            font-weight: 500;
            font-size: 24px;
            line-height: 32px;
          }
        }

        p {
          font-weight: 400;
          font-size: 14px;
          line-height: 20px;
          margin: 4px 0 24px;

          @include breakpoint-down('tabM') {
            font-weight: 400;
            font-size: 12px;
            line-height: 14px;
            margin: 4px 0 16px;
          }
        }
      }

      &__toggle {
        background: $qc-bg-osc;
        border-radius: 8px;
        display: flex;
        padding: 2px;
        gap: 12px;
        height: 38px;
        justify-content: center;
        align-items: center;
        width: 100%;
        position: relative;
        margin-bottom: 20px;

        &:before {
          background: white;
          content: ' ';
          width: calc(50% - 6px);
          height: 34px;
          border-radius: 6px;
          box-shadow: 0 1px 4px 0 #00000014;
          position: absolute;
          z-index: 1;
          left: 2px;
          transition: all 0.3s ease-in-out;
        }

        &.item2 {
          &:before {
            left: calc(50% + 4px);
          }
        }
      }

      &__item {
        background: none;
        border: 0;
        font-family: $Suisse;
        font-weight: 400;
        font-size: 14px;
        line-height: 18px;
        text-align: center;
        width: calc(50% - 6px);
        z-index: 2;
        color: #445667;
        cursor: pointer;

        &.active {
          color: #141414;
          font-weight: 700;
        }
      }

      &__inputForm {
        display: flex;
        justify-content: space-between;

        @include breakpoint-down('tabM') {
          flex-direction: column;
          justify-content: initial;
        }

        &.mode-basic {
          .investmentProfitCalculator__basic {
            @include breakpoint-down('deskM') {
              width: 100%;
            }
          }
        }

        &.mode-advanced {
          & + .investmentProfitCalculator__calculate {
            width: 100%;
          }
        }
      }

      &__basic {
        width: calc(50% - 16px);

        @include breakpoint-down('tabM') {
          width: 100%;
        }
      }

      &__advanced {
        width: calc(50% - 16px);

        @include breakpoint-down('tabM') {
          width: 100%;
        }

        &.disabled {
          pointer-events: none;
          opacity: 0.2;

          @include breakpoint-down('deskM') {
            display: none;
          }
        }
      }

      &__calculate {
        cursor: pointer;
        background: $qc-accent;
        border: 0;
        color: white;
        display: flex;
        justify-content: center;
        align-items: center;
        width: calc(50% - 16px);
        height: 42px;
        border-radius: 40px;
        margin-top: 12px;
        font-family: $Suisse;
        font-weight: 500;
        font-size: 14px;
        line-height: 18px;
        position: relative;
        z-index: 2;

        @include breakpoint-down('deskM') {
          width: 100%;
        }
      }
    }
  }
</style>