All files / src/pages/trading Trading.jsx

100% Statements 21/21
100% Branches 6/6
100% Functions 7/7
100% Lines 18/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93                  1x 1x                           7x 7x 7x 7x   7x 4x 4x   4x     4x     7x 4x     7x           7x 3x   2x               6x                                                                
import {useTranslation} from "react-i18next";
import {PageSection} from "@/components/ui/pageSection/PageSection";
import {SeoHead} from "@/components/seoHead/SeoHead";
import React, {lazy, Suspense, useEffect, useState} from "react";
import {Loading} from "@/components/loading/Loading";
import {getTradingPerformance} from "@/services/portfolioService";
import {ErrorState} from "@/components/errorState/ErrorState";
import {ButtonLink} from "@/components/ui/buttonLink/ButtonLink";
 
const TradingPerformanceChart = lazy(() =>
    import("@/components/ui/tradingPerformanceChart/TradingPerformanceChart").then(mod => ({default: mod.TradingPerformanceChart}))
);
 
/**
 * Trading component renders a section with trading introduction text,
 * description, disclaimer, a call-to-action link, and a trading performance chart.
 *
 * Uses translations for all textual content via react-i18next.
 *
 * @component
 * @module pages/trading/Trading
 * @returns {JSX.Element} The Trading page section with content and chart.
 */
export default function Trading() {
    const {t} = useTranslation();
    const [tradingPerformance, setTradingPerformance] = useState({});
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
 
    const loadTradingPerformance = () => {
        setLoading(true);
        setError(null);
 
        getTradingPerformance()
            .then(setTradingPerformance)
            .catch(setError)
            .finally(() => setLoading(false));
    };
 
    useEffect(() => {
        loadTradingPerformance();
    }, []);
 
    const paragraphs = [
        t("trading_intro"),
        t("trading_description"),
        t("disclaimer_text"),
    ];
 
    if (loading) return <Loading/>;
    if (error) return <ErrorState message={t("error_generic")} onRetry={loadTradingPerformance}/>;
 
    return (
        <>
            <SeoHead pageKey="trading" path="/trading"/>
 
            <PageSection title={t("trading_title")}>
                {/* Text above */}
                <div className="flex flex-col justify-start mb-8">
                    {paragraphs.map((text, i) => (
                        <p
                            key={i}
                            className={`${i === 2 ? "text-xs text-gray-500 dark:text-gray-400" : "text-lg text-gray-700 dark:text-gray-300"} mb-4 leading-relaxed`}
                        >
                            {text}
                        </p>
                    ))}
 
                    {/* Buttons */}
                    <div className="mt-6 flex flex-row gap-4">
                        <ButtonLink href="https://www.etoro.com/people/danielemasone" color="green">
                            {t("trading_cta")}
                        </ButtonLink>
                        <ButtonLink href="https://etoro.tw/44k4LJg" color="blue">
                            {t("trading_signup")}
                        </ButtonLink>
                    </div>
                </div>
 
                {/* Graph below that takes up all the remaining space */}
                <div className="flex-grow w-full">
                    <Suspense fallback={<Loading/>}>
                        <TradingPerformanceChart
                            startYear={tradingPerformance.startYear}
                            monthlyReturns={tradingPerformance.monthlyReturns}
                        />
                    </Suspense>
                </div>
            </PageSection>
        </>
    );
}