diff --git a/.github/workflows/generate-preview-link.yml b/.github/workflows/generate-preview-link.yml index d9ff1ad98cc..0d4d6bbd0d7 100644 --- a/.github/workflows/generate-preview-link.yml +++ b/.github/workflows/generate-preview-link.yml @@ -1,13 +1,5 @@ name: Generate preview link -permissions: - actions: write - checks: write - contents: write - deployments: write - pull-requests: write - statuses: write - on: pull_request_target: types: [opened, synchronize] @@ -24,6 +16,9 @@ concurrency: jobs: build_to_cloudflare_pages: runs-on: Ubuntu-latest + permissions: + checks: write + pull-requests: write steps: - name: Verify user uses: 'deriv-com/shared-actions/.github/actions/verify_user_in_organization@v1' @@ -32,13 +27,13 @@ jobs: token: ${{ secrets.PREVIEW_LINK_TOKEN }} - name: Checkout to repo - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 with: ref: ${{ github.event.pull_request.head.sha }} - name: 'Generate action link comment' id: generate_action_url - uses: actions/github-script@v3 + uses: actions/github-script@ffc2c79a5b2490bd33e0a41c1de74b877714d736 with: github-token: ${{ github.token }} script: | @@ -53,7 +48,7 @@ jobs: core.setOutput("comment", comment); - name: Post Cloudflare Pages Preview comment - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd with: header: Cloudflare Pages Preview Comment number: ${{github.event.pull_request.user.login}} @@ -61,7 +56,7 @@ jobs: recreate: true - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 - name: Create npmrc file shell: bash @@ -72,7 +67,7 @@ jobs: run: echo '//npm.pkg.github.com/:_authToken=${{ secrets.READ_DERIV_COM_ORG_PACKAGES }}' >> .npmrc - name: Get build output from master cache - uses: actions/cache/restore@v3 + uses: actions/cache/restore@e12d46a63a90f2fae62d114769bbf2a179198b5c with: key: master-cache-public restore-keys: | @@ -82,7 +77,7 @@ jobs: public - name: Get cached dependencies id: cache-npm - uses: actions/cache/restore@v3 + uses: actions/cache/restore@e12d46a63a90f2fae62d114769bbf2a179198b5c with: path: node_modules key: npm-${{ hashFiles('**/package-lock.json') }} @@ -145,7 +140,7 @@ jobs: - name: 'Generate preview link comment' if: success() id: generate_preview_url - uses: actions/github-script@v3 + uses: actions/github-script@ffc2c79a5b2490bd33e0a41c1de74b877714d736 with: github-token: ${{ github.token }} script: | @@ -164,7 +159,7 @@ jobs: - name: 'Generate failure comment' if: failure() id: generate_failure_comment - uses: actions/github-script@v3 + uses: actions/github-script@ffc2c79a5b2490bd33e0a41c1de74b877714d736 with: github-token: ${{ github.token }} script: | @@ -179,7 +174,7 @@ jobs: core.setOutput("comment", comment); - name: Post Cloudflare Pages Preview comment if: success() || failure() - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd with: header: Cloudflare Pages Preview Comment number: ${{github.event.number}} @@ -187,7 +182,7 @@ jobs: recreate: true - name: Upload PR information to artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@82c141cc518b40d92cc801eee768e7aafc9c2fa2 with: name: 'pr-${{github.run_id}}' path: .pr diff --git a/crowdin/messages.json b/crowdin/messages.json index bc175f8f23e..82a44621f0b 100644 --- a/crowdin/messages.json +++ b/crowdin/messages.json @@ -10,7 +10,6 @@ "7359443": "Focused accounts for a focused strategy", "7588258": "2. Click Trade on your preferred MT5 account, then click the pencil icon next to the password section.", "11019706": "Your available balance for Deriv P2P may not reflect your entire Deriv balance. This is because deposits made via some payment methods won’t be available for Deriv P2P. See <0>Why is my Deriv P2P balance different from my Deriv account balance? for more info.", - "11528850": "tnt", "13119092": "clients", "15238581": "Go to the first item in the media gallery and click <0>Get media code.", "17217397": "Cryptocurrency", @@ -34,14 +33,12 @@ "33430960": "How dynamic leverage is calculated", "33727397": "You can fund your margin account with EUR, USD and GBP. If you wish to use other currencies, please reach out to us and we will review your request.", "34997376": "Deriv in numbers", - "35374636": "user friendly icon", "36380780": "

Here's how to open a Touch/No Touch contract:

", "36614989": "To register a complaint and seek assistance, follow these easy steps", "37075461": "5
(Per USD 100k
turnover)", "39595561": "See how your bot is performing as it executes each trade and receive notifications via Telegram.", "41078219": "Get into the Deriv Trader experience", "41570825": "Are High/Low Ticks options available on Deriv Trader?", - "42762042": "Add stake amount to receive payout quote", "48235639": "The potential payout and loss (your initial stake) amounts are clearly displayed before you open the trade.", "48469443": "Complete <0>this form, and we'll get in touch with you in a couple of days.
You'll need a real Deriv trading account, too. If you don't have one, sign up <1>here.", "48763975": "What if I am unhappy with the outcome of my complaint?", @@ -160,7 +157,6 @@ "154545319": "Country of residence is where you currently live.", "154883335": "Exclusive access to innovative assets", "155518428": "graph", - "155869362": "high low", "156487821": "DEX 1500 DOWN Index", "158763587": "Check the profit", "159648667": "A chart illustrating a winning Over trade type contract", @@ -177,13 +173,11 @@ "171586173": "Discover career opportunities at Deriv across our office locations around the globe.", "171638706": "Variables", "171678405": "Can I choose the duration of a Touch/No Touch contract?", - "175068676": "Choose from forex, stocks & indices, commodities, and derived.", "175074759": "Trade when you’re free from the distractions of weekday responsibilities.", "176773798": "0.5%", "176823932": "We may decline your verification documents if they are insufficiently clear, invalid, expired, or have cropped edges.", "176972763": "<0>GLD.US The SPDR Gold Shares ETF tracks the price of gold bullion in the over-the-counter (OTC) market.", "177720589": "If you hit <0>Yes, the details you entered will be lost, and you’ll need to restart the registration process.", - "180412186": "Predict whether the exit spot will be strictly higher or lower than the entry spot at the end of the contract period.", "181754600": "How can I identify emails from impersonators of Deriv customer support?", "182234515": "Choose the type of partner account you want to register", "182438100": "Frequently asked questions - DBot", @@ -196,7 +190,6 @@ "192890975": "Can I open multiple accumulator contracts at the same time?", "193611235": "Exchange in minutes. Less waiting, more trading. Deposit and withdraw in minutes.", "194431525": "Provide a representative demo experience", - "194961269": "How options contracts work", "195031216": "Complaints procedure", "195335391": "Earn based on your sub-affiliate’s commission.", "198900889": "Can I open more than one Deriv account?", @@ -301,7 +294,6 @@ "288565174": "How much does it cost to register for the IB programme?", "288719886": "Czech Republic", "289008060": "Facebook Inc", - "290903014": "ou od", "291605393": "Greece", "291856470": "Please generate an address on the cryptocurrency deposit page whenever you want to make a deposit. Always use a freshly generated address to ensure accuracy.", "292497263": "Click on your account balance and click <0>Add or manage account.", @@ -321,7 +313,6 @@ "307902006": "Enjoy high leverage and low spreads on our Deriv MT5 platform, now offering a range of stocks and stock indices from the brands you love.", "309180597": "Expand your client base by helping traders fund their accounts through local bank wires and e-payments. Facilitate and earn from every transaction.", "309993304": "Try Deriv at no risk", - "310298121": "<0>Digital options that allow you to predict the outcome from two possible results and earn a fixed payout if your prediction is correct.", "311457810": "Our pip calculator helps you to estimate the pip value in your trades so that you can better manage your risk.", "311876462": "Send us an email with the following:", "315192357": "Swap rate", @@ -337,7 +328,6 @@ "320565687": "<0>Gold Basket measures the value of gold against a basket of five global currencies (EUR, GBP, JPY, AUD, USD), each weighted by 20%.", "322368988": "Multipliers - Synthetics: Volatility 250 (1s) Index", "323360883": "Baskets", - "325128398": "3. Duration", "326242312": "Volume in lots", "327728169": "12.5", "328362983": "0.4%", @@ -417,7 +407,6 @@ "401498558": "Deriv (FX) Ltd (Company No. LL13394), incorporated on the 18th January 2017, is registered in the Federal Territory of Labuan (Malaysia) with its registered office located at Unit No. 3A-16, Level 3A, Labuan Times Square, Jalan Merdeka, 87000, Federal Territory of Labuan, Malaysia. Deriv (FX) Ltd is licensed by the Labuan Financial Services Authority <0>(view licence) and is a member of the <1>Labuan Fintech Association.", "405110755": "You can trade forex, cryptocurrencies, and derived on Deriv Trader. Some markets may not be available in certain countries.", "405259925": "Fast CFDs platform with inbuilt copy trading.", - "406075956": "If you select ‘Odd’, you will win the payout if the last digit of the last tick is an odd number (i.e. 1, 3, 5, 7, or 9).", "406403062": "Can I change my growth rate after opening the contract?", "407739127": "A monthly service fee of USD 1,500 will be charged at the end of each month. The fee is accrued and only charged if the minimum volume requirements are not exceeded.", "408925924": "Up to x1000", @@ -453,7 +442,6 @@ "432775041": "Get Trading", "433348384": "Real accounts are not available to politically exposed persons (PEPs).", "434113887": "Frequently asked questions - Deriv MT5", - "434254071": "rc rp", "434669878": "Best forex spread award", "435601722": "Arrow", "436791456": "4. Your new Deriv cTrader account is ready.", @@ -517,7 +505,6 @@ "487236738": "How it’s calculated", "489679731": "SGD/JPY", "489777784": "EFA.US", - "491908760": "Receive payout quote or stake amount based on the position you have defined.", "492590863": "Please enter a valid URL format", "492921093": "25 - 500", "493240844": "Signup to Deriv.com and trade online with as little as $1 USD on major currencies, stocks, indices, and commodities.", @@ -669,7 +656,6 @@ "628661446": "If the selected condition is not met or if the last tick is equal to the average of all the ticks, your stake is lost.", "628823666": "Can I enter many High/Low Ticks contracts at the same time?", "629081848": "Higher/Lower Icon", - "629101274": "If you select ‘Only Downs’, you win the payout if consecutive ticks fall successively after the entry spot. No payout if any tick rises or is equal to any of the previous ticks.", "630520732": "The Deriv IB Programme is completely free.", "630831015": "Dtrader trading platform", "631600257": "Strong regulatory compliance that instils confidence in clients from all over the world.", @@ -691,7 +677,6 @@ "645902266": "EUR/NZD", "645954408": "When the market price climbs to 8,700 USD, you decide to set the stop loss level at 8,200 USD. After a few ticks, the price dives to 8,100 USD, surpassing your stop loss level. Your trade will automatically close at 8,100 USD.", "646017912": "Our flagship app for trading options and multipliers.", - "646157763": "sb go", "647610263": "synthetic indices", "648610617": "The requested URL was not found", "649962941": "2. Trade type", @@ -743,7 +728,6 @@ "699722384": "1. You must have an MQL5 community account to subscribe to trading signals. If you don't have an account yet, please go to <0>MQL5.com to register.", "700128691": "We’re steadfast in our commitment to high ethical standards. Find more reasons to know why Deriv is the choice of online traders.", "700971061": "You can find your Deriv MT5 server name on your <0>Deriv MT5 dashboard. Click Trade on your preferred MT5 account and look for the server below the broker name.", - "701236336": "Website url", "701775446": "Volatility 200 Index", "701840176": "Commission per USD 100k turnover", "702074152": "PARTNERS", @@ -775,7 +759,6 @@ "730281403": "Make instant bank transfers to all the major banks in your country.", "731382582": "BNB/USD", "731636050": "Can I open multiple turbo options contracts simultaneously?", - "732351316": "Step 3 : Address details (3 of 5)", "733057061": "Learn how to trade cryptocurrencies with Deriv", "733615113": "No, it isn’t. DP2P is a peer-to-peer service for our clients to make deposits and withdrawals using their local currency. As our payment agent, you can use the DP2P platform to offer your services to Deriv clients in your country", "733921210": "For instance, if you are trading the USD/JPY forex pair, the swap charge will be computed in Japanese Yen (JPY) which is the quote currency. On the other hand, if you are trading oil, then the swap charge will be computed in US Dollar (USD), which is the denomination of the underlying asset – oil.", @@ -800,14 +783,12 @@ "752024971": "Reached maximum number of digits", "754014828": "Start trading derived FX on Deriv in 3 simple steps", "754435349": "200+", - "754502256": "Buy contract", "755433132": "What are digital options?", "755567027": "Can payment agent offer their services to a premium payment agent?", "756066527": "I agree to the <0>terms and conditions", "756258759": "The <0>DEX 600DN has frequent small spikes and occasional major drops, which occur <0>every 600 seconds on average.", "756310599": "We will be transparent about the terms of all contracts so that customers can make informed choices.", "756453521": "Pie chart explaining relation between margin and leverage", - "757309464": "Purchase the contract if you are satisfied with the quote, or re-define your position.", "757475465": "DSI10", "758038191": "Find your role with us by browsing Deriv job opportunities in Melaka, Malaysia.", "759844711": "Yes, it's completely free of charge <0>to join.", @@ -979,7 +960,6 @@ "910806943": "You’ll earn a fixed commission based on the volume of individual trades bought by your referred clients.", "912406629": "Follow these steps:", "913276286": "1. Go to your <0>Deriv MT5 dashboard.", - "913719394": "If you select ‘Over’, you will win the payout if the last digit of the last tick is greater than your prediction.", "915392164": "Open long or short positions based on your predictions of the market price movements.", "915554307": "Your potential. Our technology.", "916591715": "The above information is updated monthly and, therefore, may not reflect current trading conditions.", @@ -993,7 +973,6 @@ "922601177": "CPA", "925239281": "How do I withdraw funds from my Deriv X real money account?", "927364570": "<0>Setting > Proof of address", - "927510190": "Predict whether the market will stay inside or go outside two price targets at any time during the contract period.", "927830157": "User-friendly platforms with powerful chart widgets", "929514030": "Enjoy trading asset prices derived from simulated markets.", "929553858": "They ask you to download file attachments or remote access software (such as Teamviewer) to give them remote control of your device. For example, an impersonator may take control and install ransomware on your device and then demand a ransom. If the ransom isn’t paid, you may lose access to your device permanently.", @@ -1053,10 +1032,8 @@ "982146443": "WhatsApp", "983081962": "Master affiliate", "987462335": "payment methods", - "992411597": "If you select ‘Even’, you will win the payout if the last digit of the last tick is an even number (i.e. 2, 4, 6, 8, or 0).", "992485806": "Your position is automatically closed when your stop loss level is at <0>1.1750 and when your stop loss pip value is <0>24 USD.", "993380717": "info symbol", - "995624454": "Target position", "1000512133": "API", "1000991093": "Forex online trading platforms | Forex trading demo account | Deriv", "1001160515": "Sell", @@ -1089,7 +1066,6 @@ "1024756670": "Trade on multiple markets", "1025026772": "Jump indices correspond to simulated markets with large, sudden price changes. They have constant volatilities ranging from 10% to 100%.", "1025032938": "Do I have to pay any fees to become a payment agent for Deriv?", - "1026160856": "Predict whether the last digit of the last tick of a contract will be an even number or an odd number.", "1026344937": "Please contact our Customer Support team via <0>live chat if you have doubts or concerns.", "1026845997": "Endpoint", "1027349186": "First Name", @@ -1209,6 +1185,7 @@ "1136360582": "In this e-book we will cover", "1136731907": "Note that these are approximate values only and will differ depending on the leverage that is set for your account and the asset you want to trade.", "1138338302": "If you're residing in the EU, <0>contact us via live chat, and we'll help you with it.", + "1138813036": "Something went wrong. Please check your details and try again.", "1139331057": "You will receive a payout if the spot price remains above a predetermined barrier throughout the entire trade duration. If the spot price touches or breaches the barrier at any time before the contract expires, the initial stake (premium) is lost.", "1141200231": "Spain 35", "1145468876": "Trade on the world’s most popular cryptocurrencies and potentially profit from correctly anticipating price movements.", @@ -1217,7 +1194,6 @@ "1149190992": "Trade selected derived and financial assets without overnight charges.", "1150115412": "1. Please log in to your account and go to the “Manage account settings”.", "1150953111": "Tight spreads", - "1151925602": "Predict whether the last digit of the last tick of a contract will be higher or lower than a specific number.", "1153826782": "A sub-affiliate earns USD 200 from their Revenue Share plan. The same sub-affiliate earns USD 100 from their IB programme. Here is how we calculate their total commissions:", "1155361880": "Need help? Please <0>contact us via live chat.", "1155971726": "Click <0>here to close your account.", @@ -1239,7 +1215,6 @@ "1171083830": "Hit <0>Get next to <0>Deriv account.", "1171332705": "Username*", "1171765024": "Step 3", - "1172611503": "If you select ‘Asian Fall’, you will win the payout if the last tick is lower than the average of the ticks.", "1172806588": "Make instant deposits using your local e-wallet.", "1175717636": "What kind of reports can I generate from my affiliate account?", "1177080017": "DBot | Trading robot | Deriv", @@ -1530,7 +1505,6 @@ "1435321289": "Process all deposits and withdrawals quickly and accurately", "1435793182": "Predict whether the exit spot will be higher or lower than either the entry spot or the spot at reset time.", "1437505451": "Pip Calculator", - "1437672633": "Step 4 : Personal details (4 of 5)", "1438632095": "Please enter a valid company registration number.", "1442199408": "Deriv MT5 trading platform", "1444503524": "Trade CFDs, options, and multipliers", @@ -1541,7 +1515,6 @@ "1451636739": "Intuitive tools", "1452901553": "Derived trading gives you a chance to make a profit from correctly predicting the price movement of instruments that mimic characteristics of financial markets or are derived from them.", "1454068319": "To use Deriv P2P, you’ll first need a Deriv real USD account. If you don’t already have one, <0>sign up for free.", - "1454189755": "If the exit spot is equal to either the low barrier or the high barrier, you don't win the payout.", "1454243296": "Minimal capital requirements, limited risk", "1454599585": "<0>Escrow fund protection", "1456673219": "How and when will I receive my commission payout?", @@ -1554,7 +1527,6 @@ "1462469069": "Make deposits and withdrawals using your credit and debit cards.", "1464424169": "Contract size", "1464468524": "Tanzania", - "1466745668": "Predict what number will be the last digit of the last tick of a contract.", "1466788657": "For more info, <0>check out this blog post on the basics of building a trading bot.", "1467325385": "Global affiliate support", "1467514183": "Virtual markets, real opportunities.", @@ -1617,7 +1589,6 @@ "1516021730": "20 - 1,000", "1516676261": "Deposit", "1518575473": "Uptime", - "1519951161": "Space not available", "1523687535": "We don’t pay commission, but you can set your own commission rate per transaction within reasonable thresholds. When you sign up, our team will be in touch to work out the details with you.", "1524248407": "Trade on financial markets plus our proprietary synthetics that are available 24/7.", "1524725659": "When will the commission be paid out?", @@ -1648,7 +1619,6 @@ "1549497379": "High leverage, tight forex spreads", "1550413103": "checklist", "1550574351": "Let’s say you want to keep two lots of EUR/USD with a point value of 0.00001 and swap rate of -0.12 open for one night.", - "1551153165": "You can trade the following options on Deriv:", "1551172020": "AUD Basket", "1552847627": "Know all the details about how you can become the payment agent on Deriv. Send us an email to apply!", "1553185861": "partnership programmes", @@ -1669,7 +1639,6 @@ "1559712313": "Commodity trades available on Deriv", "1560383409": "Android", "1561008060": "", - "1562241070": "All favourite markets and more", "1563919822": "You'll get daily commission payouts in your MT5 Synthetic account.", "1565046344": "Click on unofficial links and files.", "1565220133": "you reside in the UK, or", @@ -1680,6 +1649,7 @@ "1569743220": "Let's start", "1571653008": "Use our free demo account, and trade with unlimited virtual funds. It’s the easiest way to learn how to use our products.", "1571816719": "What is a referred client?", + "1572726293": "You should enter 8-50 characters.", "1573231398": "Why trade cryptocurrencies on Deriv", "1573429525": "Call/Put", "1573589662": "Do keep in mind that we do not allow unauthorised incentives, gifts, and payments to encourage client signups. Payment will be withheld if any suspicions or activity of this conduct is discovered.", @@ -1757,13 +1727,11 @@ "1628981793": "Can I trade cryptocurrencies on Deriv Bot?", "1631281562": "GBP Basket", "1631620531": "Years of industry experience", - "1631705059": "Predict whether the exit spot will be higher or lower than a price target (the barrier) at the end of the contract period.", "1633022779": "Synthetic indices and cryptocurrencies are available for trading 24/7.", "1633102593": "Software developers", "1633767238": "Use this account to log in to <0>Deriv and <0>Deriv Academy.", "1634507782": "Range Break 200 Index", "1634696689": "From (lots)", - "1635959746": "high close", "1636039779": "Road Town, British Virgin Islands – Our team | Deriv", "1636066113": "Partnership opportunities", "1636527166": "Forex trades available on Deriv", @@ -1787,8 +1755,8 @@ "1650136049": "Walmart Inc", "1650771580": "Energy (Oil)", "1651159021": "Your cTrader account is linked to your Deriv account. <0/>Please click the button to proceed with <1>deleting your Deriv account.", + "1651512202": "Step 3 : Personal details (3 of 5)", "1651972947": "Open a real account, make a deposit, and start trading multipliers for real.", - "1652448981": "hl ticks", "1652756662": "Open a digital options contract with an In/Out trade type on Deriv’s trading platforms and earn payouts with accurate market predictions.", "1653650288": "Market-based values with limited influence from real-world events", "1654085043": "A chart illustrating a losing Lower trade type contract", @@ -1903,7 +1871,6 @@ "1753559268": "We'll pay your IB commission into your MT5 Synthetic account daily.", "1755228338": "Securing your account", "1756407392": "Terms of cooperation", - "1757587944": "close low", "1758111931": "active users", "1758663702": "It refers to the exchange rate used in Deriv P2P ads. In some countries where it isn't feasible to use a fixed exchange rate (due to market volatility), you can set the exchange rate for your ad to a specific percentage of the market price.", "1758803741": "- Enter your stake amount.", @@ -1916,14 +1883,12 @@ "1767992960": "Sounds great. Let's get started.", "1768089459": "Paris | Our office – France | Deriv", "1769159485": "Yes, you can open multiple Reset Call/Reset Put contracts with different durations and different stake amounts or desired potential payouts at the same time.", - "1770479100": "If you select ‘Higher’, you win the payout if the exit spot is strictly higher than the barrier.", "1771323174": "rise fall", "1771364541": "5. You'll be taken to the Change password screen. Enter a new password and click Create.", "1771672206": "The <0>DEX 900UP has frequent small drops and occasional major spikes, which occur <0>every 900 seconds on average.", "1772047578": "Why are my Deriv MT5 login details different from my Deriv login details?", "1772406884": "Deriv P2P is good. It’s easy to deposit and withdraw for small traders.", "1773351605": "The completion rate is the percentage of orders that the advertiser could complete within 1 hour.", - "1774791951": "Predict whether the exit spot will be inside or outside two price targets at the end of the contract period.", "1781738442": "reset call/reset put option trade", "1782703044": "Sign up", "1783526986": "How do I build a trading bot?", @@ -1965,7 +1930,6 @@ "1813700208": "Boom 300 Index", "1813703795": "Sign up as our affiliate and IB", "1813982788": "Deriv (FX) Ltd is licensed by the Labuan Financial Services Authority <0>(licence). Deriv (BVI) Ltd is licensed by the British Virgin Islands Financial Services Commission <1>(licence). Deriv (V) Ltd is licensed by the Vanuatu Financial Services Commission <2>(licence). Deriv (SVG) LLC has a registered office at First Floor, SVG Teachers Credit Union Uptown Building, Corner of James and Middle Street, Kingstown P.O., St Vincent and the Grenadines. The holding company for these subsidiaries is Deriv.com Limited, with the registration number 71479 and the registered address at 2nd Floor, 1 Cornet Street, St Peter Port, Guernsey, GY1 1BZ.", - "1815044592": "If you select ‘Only Ups’, you win the payout if consecutive ticks rise successively after the entry spot. No payout if any tick falls or is equal to any of the previous ticks.", "1815324634": "The minimum deposit and withdrawal amount varies depending on the payment method. The lowest deposit and withdrawal amount is 5 USD/EUR/GBP/AUD via e-wallets. See our <0>Payment methods page for a complete list of payment methods and their minimum deposit and withdrawal amounts.", "1816305227": "If you’re in the EU or UK:", "1817888235": "Predict and gain from exciting spikes and dips with our Crash/Boom indices.", @@ -2014,7 +1978,6 @@ "1857302542": "Can I open a corporate or business account?", "1858113285": "Yes, you can open multiple contracts at the same time to take advantage of market opportunities.", "1858147490": "Just drag the XML file from your computer onto the workspace, and your bot will be loaded accordingly. Alternatively, you can hit <0>Import in <0>Bot Builder, and choose to import your bot from your computer or from your Google Drive.", - "1859772193": "If you select ‘Allow equals’, you win the payout if the exit spot is higher than or equal to the entry spot for ‘Rise’. Similarly, you win the payout if the exit spot is lower than or equal to the entry spot for ‘Fall’.", "1860472068": "Online banking", "1861302455": "You can place an In/Out trade by:", "1862283751": "Trade forex, synthetic indices, and cryptocurrencies wherever, whenever you want and maximise your potential profit with multipliers on Deriv GO.", @@ -2081,6 +2044,7 @@ "1905380076": "Settle the payment with the counterparty of your transaction.", "1905702565": "Client money protection", "1906101554": "You’ll earn a payout based on the volume of your clients' trades. Find out more <0>here.", + "1906507843": "Step 4 : Subscription plan (4 of 5)", "1906568376": "There was an error fetching the live pricing data", "1907226338": "Coca-Cola", "1907562333": "You will receive a payout if the spot price remains below a predetermined barrier throughout the entire trade duration. If the spot price touches or breaches the barrier at any time before the contract expires, the initial stake (premium) is lost.", @@ -2093,7 +2057,6 @@ "1911713696": "No, your account safety is your sole responsibility. Please visit our <0>blog to learn safety tips on identifying and reporting phishing attempts.", "1912846049": "To trade High/Low Ticks, all you need to do is predict which of the next 5 ticks within the contract period is the highest or lowest in the series.", "1913017782": "A chart illustrating a losing Asian Down trade type contract", - "1914042845": "matches differs", "1914696793": "Here are some ways to identify impersonators of Deriv customer support:", "1914949637": "What is the Deriv Affiliate Programme?", "1915387440": "If you’re selling:", @@ -2116,7 +2079,6 @@ "1930677092": "Fill up the form and hit <0>Post ad.", "1931163835": "What is forex?", "1932481526": "laptop dtrader eu", - "1932561482": "Buy the contract", "1933869329": "Cancel and close features are not allowed simultaneously.", "1934290400": "<0>Deriv X is an-easy-to-use trading platform where you can trade CFDs on various assets on a platform layout that you can customise according to your preference.", "1935201826": "Earn based on the monthly net revenue generated by your clients.", @@ -2144,7 +2106,6 @@ "1955645943": "Sub-affiliate’s total commission: 200 + 100 = USD 300 (including IB commission)", "1958336398": "This formula also applies to <0>ETFs. Contract sizes and deal prices depend on the individual asset.", "1958538866": "Oil", - "1959548433": "Set the duration of your trade. Depending on whether you have a short-term or long-term view of the markets, you can set your preferred duration, starting from 1 to 10 ticks or 15 seconds to 365 days.", "1959678342": "Highs & Lows", "1961462165": "4. Hit Add real account or Add demo account.", "1962097923": "Help centre | Frequently asked questions | IB programme | Deriv", @@ -2169,7 +2130,6 @@ "1979503547": "Trading terms", "1980724783": "The point value is derived from the current digits of the asset. In this example, the digit is 5, so the point value is 0.00001.", "1981714597": "The world’s most popular digital currencies.", - "1982404952": "Get quote", "1983480826": "Sign in", "1983854834": "24/7 trading with the world’s top crypto assets.", "1984717496": "After you send your complaint through live chat, our team will review the information you provided. You'll get a response to your complaint or updates on its status via email.", @@ -2177,7 +2137,6 @@ "1986498784": "BTC/LTC", "1987441296": "What is Deriv MT5?", "1988153223": "Email address", - "1988527170": "If you select ‘No Touch’, you win the payout if the market never touches the barrier at any time during the contract period.", "1989494280": "If you're not satisfied with the answer you get from our customer support team, you can make a formal complaint by contacting our compliance team at <0>complaints@deriv.com. They will review your complaint independently to see if we treated you fairly within our rights and our contractual obligations to you. For more details, log in to your account and check our <1>complaints policy. It explains the steps you can take for further help.", "1990796034": "360", "1991022173": "Total commission earned: 10 x 0.5% = USD 0.05", @@ -2191,7 +2150,6 @@ "1995407297": "Earn 100 USD when a referred client deposits 100 USD in their Deriv account, whether it's a one-time deposit or accumulated over time. It's simple, transparent, and rewarding!", "1995896523": "DMT5 is developed to give you the best CFD trading experience. You can access our MT5 trader through desktop and even mobile.", "1996332377": "1 ) }", - "1997138507": "If the last tick is equal to the average of the ticks, you don't win the payout.", "1997358332": "download deriv-go", "1998203837": "Safe and secure", "1998452473": "Earn up to 45% lifetime commission with an online trading provider that enables anyone to trade on several popular financial markets with the utmost convenience. Deriv Group Ltd — the owner of Deriv.com — has a proven track record of running successful referral programmes with prompt payouts.", @@ -2242,7 +2200,6 @@ "2036876215": "<0>Forex at your fingertips. Currency trading with major, minor, and exotic pairs. ", "2041571225": "- Brokerage firms", "2041763181": "Once we've paid your commission into your account, you can withdraw whenever you want.", - "2042720038": "High Ticks/Low Ticks, Asians, Reset Call/Reset Put, Digits, and Only Ups/Only Downs are available exclusively on synthetics.", "2043507434": "Here's what you can do:", "2044967354": "You can see your available balance in the <0>My profile tab.", "2044999022": "Trade jump indices, the new synthetics with a twist", @@ -2271,7 +2228,6 @@ "2062902293": "To open a Up/Down contract, you'll need to:", "2062903400": "Set a limit", "2063623452": "status", - "2063987970": "<0>Lookbacks that allow you to earn a payout depending on the optimum high or low achieved by the market during the duration of a contract.", "2064152905": "Maximize Potential Profit", "2064273783": "Cashier limits", "2064293002": "You can’t set a take profit level when you purchase a multipliers contract with deal cancellation. However, once the deal cancellation expires, you can set a take profit level on the open contract.", @@ -2341,7 +2297,6 @@ "2127031078": "Available to trade 24/7 on popular crypto assets", "2127438954": "For synthetic, the swap charge is calculated on an annual basis for long and short positions based on this formula:", "2127504445": "Once you have determined the above parameters, you can open an Asians trade on SmartTrader and Deriv Bot.", - "2129099656": "Select your desired trade type — Up and Down, High and Lows, Digits, etc.", "2130006600": "Deriv P2P is a flawless innovation.", "2130618063": "Yes, you can enter multiple contracts with varying parameters at the same time.", "2130695061": "Cookies help us to give you a better experience and personalised content on our site. ", @@ -3086,8 +3041,6 @@ "-207591979": "Deriv <0>multipliers combines the upside of leverage trading without the downside of losing more than your stake. This means that when the market moves in your favour, you'll multiply your potential profits. If the market moves against your prediction, your losses are limited only to your stake. To find out more, visit the <0>Multipliers page.", "-771604768": "How do I trade multipliers?", "-1755209362": "Watch <0>this video to know more about trading multipliers.", - "-240686434": "Reliable.", - "-396178446": "100+ tradeable assets", "-456233007": "It is a partnership arrangement where a payment agent is authorised to process deposits and withdrawals for our clients.", "-898245410": "Are there any fees I need to pay to become a payment agent on Deriv?", "-173947736": "As a payment agent, you determine your commission per transaction, subject to our established thresholds.", @@ -3130,8 +3083,8 @@ "-1793883644": "Trade FX and CFDs on a customisable, easy-to-use trading platform.", "-1781346745": "Discover Deriv X now", "-279398477": "Trade the world’s markets on <0>Binary.com’s classic platform.", - "-1781881664": "Check out our other platform", "-2130720993": "Check out our other platforms", + "-1781881664": "Check out our other platform", "-1825471709": "A whole new trading experience on a powerful yet easy to use platform.", "-204498543": "Trade with leverage and tight spreads for better returns on successful trades.", "-2115275974": "CFDs", @@ -3684,12 +3637,14 @@ "-1859212587": "Frequently asked questions - Payment Agent", "-1618901770": "Help centre | Frequently asked questions | Trading | Deriv", "-2085755369": "Frequently asked questions - Trading", - "-542307428": "world map", - "-1360155081": "Take part in the world’s largest financial market where more than $5 trillion worth of currencies are bought and sold each day.", + "-240686434": "Reliable.", + "-396178446": "100+ tradeable assets", "-1894673375": "mobile app deriv go", "-505163259": "laptop dtrader", "-1633415532": "laptop deriv x", "-404595524": "laptop dmt5 eu", + "-542307428": "world map", + "-1360155081": "Take part in the world’s largest financial market where more than $5 trillion worth of currencies are bought and sold each day.", "-313388618": "Dtrader trading platform at Deriv", "-717865028": "Anywhere. Anytime.", "-1708710909": "We’re 25 years strong", @@ -3802,9 +3757,9 @@ "-305466448": "Trade your favourite currency against a basket of major currencies and benefit from reduced risk and volatility.", "-1416860311": "Start trading baskets on Deriv in 3 simple steps", "-785091863": "Open a real account, make a deposit, and start trading commodities and other markets. ", - "-1655759142": "1:2 leverage", "-628881664": "1:100 leverage", "-2058127891": "1 to 100 leverage", + "-1655759142": "1:2 leverage", "-136024734": "tight spreads", "-544982451": "Crypto currency pairs", "-819550264": "Zero commission", @@ -4049,6 +4004,7 @@ "-1943991243": "Partnership with a trusted pioneer", "-1781913728": "Benefit from our extensive experience of more than 20 years and our internationally acclaimed reputation.", "-1994716313": "No charges or hidden fees", + "-1669980379": "Sign up as our affiliate", "-13699993": "Deriv Affiliate Programme", "-806909894": "Partner with us as an affiliate. Earn commission from your referred client’s deposits.", "-1067164259": "Partner with us as an affiliate. Earn commission from the total net revenue of your referred clients’ trades on Deriv Trader, Deriv Bot, and SmartTrader.", @@ -4168,6 +4124,11 @@ "-1664474688": "Fill out the online application form. We’ll review your application and get in touch once it’s approved.", "-1253892742": "Advertise", "-2139211466": "Use your unique affiliate link and our tried-and-tested referral tools to bring new clients to Deriv.", + "-871158567": "Deriv Affiliate Programme is free. Enjoy reliable payouts by getting your affiliate commissions paid to your Deriv account.", + "-903553712": "Start off as an affiliate and get ensuing access to our IB programme. Earn commission for as long as your referred clients keep trading.", + "-2090447319": "DMT5 and Dtrader trading platform at Deriv", + "-1299009682": "Optimise conversions with great user experience and creative support", + "-1657692765": "Marketing creative material", "-2096939984": "Why partner with us", "-1379332802": "Earn based on each successful referral.", "-1706697508": "This plan is available exclusively for EU-based clients. Please note that according to regulations, you cannot have clients who reside in Portugal or Spain.", @@ -4179,12 +4140,6 @@ "-53651607": "Disclaimer: Affiliates not residing in the EU may sign up for the CPA plan.", "-704590302": "You earn <0>USD 100 when your new referred client deposits and trades a total amount of <0>USD 100 or its equivalent into their Deriv account, either in one deposit or cumulatively.", "-1794572884": "Affiliates not residing in the EU may sign up for the CPA plan.", - "-1669980379": "Sign up as our affiliate", - "-871158567": "Deriv Affiliate Programme is free. Enjoy reliable payouts by getting your affiliate commissions paid to your Deriv account.", - "-903553712": "Start off as an affiliate and get ensuing access to our IB programme. Earn commission for as long as your referred clients keep trading.", - "-2090447319": "DMT5 and Dtrader trading platform at Deriv", - "-1299009682": "Optimise conversions with great user experience and creative support", - "-1657692765": "Marketing creative material", "-1201069751": "Master Affiliate", "-1625742908": "This plan is not available for affiliates who promote to clients residing in the EU.", "-82217352": "Sub affiliate’s total commission: USD 300", @@ -4311,6 +4266,9 @@ "-2121510827": "Sweden", "-1357648282": "For fair resolution of any complaints, please <0>chat with us. To learn more, see our <1>complaint policy.", "-1838458999": "For fair resolution of any complaints, please <0>chat with us.", + "-1131400885": "Deriv Investments (Europe) Limited", + "-1231248751": "Deriv Investments (Europe) Limited (Company No. C 70156), incorporated on the 22nd April 2015, is registered in Malta with its registered office located at Level 3, W Business Centre, Triq Dun Karm, Birkirkara BKR9033, Malta. Deriv Investments (Europe) Ltd is licensed in Malta and regulated by the Malta Financial Services Authority under the Investments Services Act <0>(view licence) to provide investment services.", + "-2051445931": "Clients in the European Union who wish to trade financial instruments can have accounts under Deriv Investments (Europe) Limited.", "-1446148261": "CFDs - Forex", "-1121949345": "CFDs - Stock indices", "-33096025": "CFDs - Cryptocurrencies", @@ -4318,9 +4276,6 @@ "-1238176624": "CFDs - Synthetics: Volatility 250 (1s) Index", "-1076679821": "Multipliers - Cryptocurrencies", "-812435767": "Multipliers - Synthetics: Crash 300 Index", - "-1131400885": "Deriv Investments (Europe) Limited", - "-1231248751": "Deriv Investments (Europe) Limited (Company No. C 70156), incorporated on the 22nd April 2015, is registered in Malta with its registered office located at Level 3, W Business Centre, Triq Dun Karm, Birkirkara BKR9033, Malta. Deriv Investments (Europe) Ltd is licensed in Malta and regulated by the Malta Financial Services Authority under the Investments Services Act <0>(view licence) to provide investment services.", - "-2051445931": "Clients in the European Union who wish to trade financial instruments can have accounts under Deriv Investments (Europe) Limited.", "-112814932": "Deriv (FX) Ltd", "-1269257733": "Clients in the rest of the world (except for restricted countries such as the USA, Canada, and Hong Kong) who wish to trade CFDs on forex and cryptocurrencies can have MT5 Financial STP accounts under Deriv (FX) Ltd.", "-2019617323": "Deriv (BVI) Ltd", @@ -4380,7 +4335,6 @@ "-1918023753": "Our introducing broker programme is available to all Deriv affiliates. Earn commission from your clients' trades on Deriv's CFD trading platforms.", "-498923246": "Want to sign up as a trader?", "-1760596315": "Create a Deriv account", - "-573454478": "User name", "-1986150937": "Thank you for signing up", "-1598032031": "Your application has been received. We’re processing your application. You can expect to hear back from us within 3 to 5 business days.", "-2017825013": "Got it", @@ -4391,22 +4345,26 @@ "-830224473": "Your website is not a valid entry. Please enter another:", "-1129605560": "Change website url", "-1754713622": "Step 1 : Account type (1 of 5)", - "-1691254967": "Step 2 : Subscription plan (2 of 5)", - "-1085862265": "Subscription plan", + "-1939587587": "Step 2 : Address details (2 of 5)", "-730447440": "Address details", "-1823540512": "Personal details", "-1130147753": " Details", + "-1085862265": "Subscription plan", "-990526713": "Step 5 : Terms of use (5 of 5)", "-204765990": "Terms of use", "-26610045": "Add an affiliate account", "-435672026": "Wrong email", - "-265889213": "Empty input not available", - "-1302509916": "You should enter 2-256 characters.", + "-37998160": "Please enter 3-20 Latin characters, numbers.", + "-1458676679": "You should enter 2-50 characters.", "-442533603": "Incorrect company name", + "-859572487": "You should enter 2-20 characters.", "-840841662": "Only Latin characters", + "-420140433": "Company registration number is required", + "-173029411": "You should enter 2-20 numbers, characters.", "-1430656728": "Password is required", + "-2092237088": "You should enter 2-10 numbers, characters.", "-1049534775": "Please enter a valid postcode with Latin characters.", - "-420140433": "Company registration number is required", + "-1979098157": "Website url is required", "-1857429287": "Last Name", "-1702877392": "Important guidelines", "-776458472": "General terms of use", @@ -4497,9 +4455,6 @@ "-172868994": "Swap-free MT5 account", "-501519580": "Leave your trades open overnight with no additional charges.", "-2146727212": "Swap free", - "-894512007": "favourite markets icon", - "-252740007": "instant access icon", - "-1156092900": "flexible icon", "-544150655": "Markets available for margin trading", "-867909844": "Access over 30 assets and also trade with up to 1:30 leverage and zero commission on trades.", "-309438223": "Trade synthetic indices on margin 24/7 without being affected by natural events and liquidity risks.", @@ -4548,49 +4503,6 @@ "-1244549672": "<0>With a x500 multiplier, if the market goes up by 2%, you'll gain 2% * $100 * 500 = <1>$1,000 profit.", "-1303172083": "Why trade multipliers on Deriv", "-756921141": "Multipliers trading | Trade multipliers on Deriv", - "-60381462": "Select the market, trade type, duration, and specify your stake amount.", - "-1054534184": "Receive quote", - "-2141285771": "How to buy your first options contract on Deriv Trader", - "-297174227": "Select from different market options", - "-133449964": "Select trade type", - "-2032405405": "Select trade duration", - "-1662723022": "Enter your stake amount to receive a payout quote instantly. Alternatively, you can set your preferred payout to receive a price quote for a corresponding stake amount.", - "-53990004": "5. Get quote", - "-1120317207": "Based on the position you’ve defined, you’ll instantly receive a payout quote or a quote of the stake required to open your position.", - "-503837483": "Check stake and payout quote", - "-1523116280": "6. Purchase your contract", - "-1814731175": "Place your order immediately if you are satisfied with the quote that you’ve received. Otherwise, continue to customise the parameters and purchase your contract when you are comfortable with the quote.", - "-1421344186": "Options to trade on Deriv", - "-738060807": "Lookback options are available only on synthetics.", - "-1909665449": "If you select ‘Rise’, you win the payout if the exit spot is strictly higher than the entry spot.", - "-1749271888": "If you select ‘Fall’, you win the payout if the exit spot is strictly lower than the entry spot.", - "-1813951531": "If you select ‘Lower’, you win the payout if the exit spot is strictly lower than the barrier.", - "-1350745673": "If the exit spot is equal to the barrier, you don't win the payout.", - "-82471581": "eb eo", - "-920739960": "If you select ‘Ends Between’, you win the payout if the exit spot is strictly higher than the low barrier and lower than the high barrier.", - "-1039129655": "If you select ‘Ends Outside’, you win the payout if the exit spot is either strictly higher than the high barrier, or strictly lower than the low barrier.", - "-907391200": "If you select ‘Stays Between’, you win the payout if the market stays between (does not touch) either the high barrier or the low barrier at any time during the contract period.", - "-248048003": "If you select ‘Goes Outside’, you win the payout if the market touches either the high barrier or the low barrier at any time during the contract period.", - "-972537755": "If you select ‘Matches’, you will win the payout if the last digit of the last tick is the same as your prediction.", - "-1754746990": "If you select ‘Differs’, you will win the payout if the last digit of the last tick is not the same as your prediction.", - "-1537348701": "even odd", - "-1491344194": "over under", - "-1163143636": "If you select ‘Under’, you will win the payout if the last digit of the last tick is less than your prediction.", - "-878562744": "If you select ‘Reset-Call’, you win the payout if the exit spot is strictly higher than either the entry spot or the spot at reset time.", - "-1521910502": "If you select ‘Reset-Put’, you win the payout if the exit spot is strictly lower than either the entry spot or the spot at reset time.", - "-1272255095": "If the exit spot is equal to the barrier or the new barrier (if a reset occurs), you don't win the payout.", - "-2098235974": "If you select ‘High Tick’, you win the payout if the selected tick is the highest among the next five ticks.", - "-1166672974": "If you select ‘Low Tick’, you win the payout if the selected tick is the lowest among the next five ticks.", - "-456966889": "If you select ‘Touch’, you win the payout if the market touches the barrier at any time during the contract period.", - "-246310798": "asians", - "-1689874327": "Predict whether the exit spot (last tick) will be higher or lower than than the average of the ticks at the end of the contract period.", - "-2017493224": "If you select ‘Asian Rise’, you will win the payout if the last tick is higher than the average of the ticks.", - "-1837159865": "When you purchase a ‘High-Close’ contract, your win or loss will be equal to the multiplier times the difference between the high and the close over the duration of the contract.", - "-1883190495": "When you purchase a ‘Close-Low’ contract, your win or loss will be equal to the multiplier times the difference between the close and the low over the duration of the contract.", - "-1375354108": "When you purchase a ‘High-Low’ contract, your win or loss will be equal to the multiplier times the difference between the high and the low over the duration of the contract.", - "-2138295691": "What are options?", - "-1504129614": "Options are products that allow for payouts from predicting market movements, without needing to buy the underlying asset. You only need to open a position that predicts how the asset will move over a period of time. This makes it possible for people to participate in the financial markets with minimal capital investment.", - "-1746360444": "Options available on Deriv", "-659039661": "Accumulator options | Trade options | Deriv", "-615241025": "Open a digital options contract with a Lookbacks trade type on Deriv’s trading platforms and earn payouts with accurate market predictions.", "-1225084394": "Open a digital options contract with an Only ups/Only downs trade type on Deriv’s trading platforms and earn payouts with accurate market predictions.", diff --git a/documents/avoid-minified-error.md b/documents/avoid-minified-error.md new file mode 100644 index 00000000000..7648e3301b6 --- /dev/null +++ b/documents/avoid-minified-error.md @@ -0,0 +1,127 @@ +## Avoid minified error + +When we updated our React version to the latest we had many console errors which was related to React Hydration + +React rehydration errors (`uncaught error: minified React error #423 and #418`) happen when the client render doesn't match the server render. This can happen when using SSR or SSG, often done with Gatsby or Next.js. + +### Most common causes of hydration error: + +#### Table element is missing and + +I have found out that if you don't include the `` and `` elements on your table, React will give you a hydration error. Those elements are optional, so normally aren't required in HTML, but they are required when doing SSR / SSG with React. The reason for that is that the two elements will be added by browsers to the DOM if they are missing, but client-side rendering doesn't add them to React's shadow DOM. This gives a mismatch of the table data between the static HTML data DOM and client side render, resulting in a hydration error. + +Note: we are not allowed to use div element inside tr, th, td + +#### Repeating your code won't return the same result + +For example generating a random number can't be replicated. The code has to return the same thing when it is run on build time and on client-side. A fix for this is to either make the code repeatable or make it only run on client-side. + +#### Missing closing tag for an element + +If you forget to close an element, it can give a hydration error. + +#### Invalid HTML structure + +Invalid HTML structure can give a hydration error. For example this is incorrect HTML: `

This is a heading

`. What makes that invalid is the fact that headings can't be placed inside paragraphs. + +Another common mistake is accidentally double quoting paragraphs, this is invalid: `

Paragraph

` + +since we are using `Localize` components we are using this bad practice in many places for example we are passing a Localize inside our `p` element and we are passing a div as a component to the Localize :sweat_smile: + +```javascript +// bad practice + +content: { + text: '_t_Our GitHub repositories: <0>github.com/binary-com_t_', + components: [
], +}, +``` + +Please pass the key to the right element :sweat_smile: and make sure that the key is unique + +```javascript +// bad practice + +{items.map(({ translation_text, translation_components, sub_items, img }) => ( + <> + + ))} +``` + +#### React.useEffect doesn't work like this in the React 18 + +```javascript + useEffect(() => setSelected(default_step), [items, default_step]) +``` + +You will get destroy is not a function error! + +Instead you should use it like this: + +```javascript + useEffect(() => { + setSelected(default_step) + }, [items, default_step]) +``` + +#### Content Change based on region + +The regional conditions for EU and ROW content have changed. First, we adjust a local state, and subsequently update the content based on that state. + +**This will give error:** + +```javascript + const { is_eu } = useRegion() + return ( + + ) +``` + +**Do this insted:** + +```javascript + const { is_eu } = useRegion() + const [items, setItems] = useState(mainRowNavItems) + + useEffect(() => { + if (is_eu) setItems(mainEuNavItems) + }, [is_eu]) + + return ( + + ) +``` + +**Or do this:** + +```javascript + const { is_eu } = useRegion() + const [show_digital_options, setShowDigitalOptions] = useState(true) + + useEffect(() => { + if (is_eu) { + setShowDigitalOptions(false) + } + }, [is_eu]) + + return ( + Digital options content

+ } + /> + ) +``` \ No newline at end of file diff --git a/gatsby-browser.js b/gatsby-browser.js index b025307f662..7871256cb87 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -1,5 +1,4 @@ import React from 'react' -import { createRoot } from 'react-dom/client' import Cookies from 'js-cookie' import { isMobile } from 'react-device-detect' import { Analytics } from '@deriv-com/analytics' @@ -23,13 +22,6 @@ import '@deriv-com/blocks/style.css'; const is_browser = typeof window !== 'undefined' -export const replaceHydrateFunction = () => { - return (element, container) => { - const root = createRoot(container) - root.render(element) - } -} - const checkDomain = () => { return eval( decodeURIComponent( @@ -99,11 +91,19 @@ export const onClientEntry = () => { ? process.env.GATSBY_RUDDERSTACK_STAGING_KEY : process.env.GATSBY_RUDDERSTACK_PRODUCTION_KEY, }) + const utm_data = JSON?.parse( + Cookies?.get('utm_data') || + `{"utm_source":"common","utm_medium":"common","utm_campaign":"common"}`, + ) Analytics?.setAttributes({ - country: Cookies.get('clients_country') || Cookies.getJSON('website_status'), - user_language: Cookies.get('user_language') || getLanguage(), + country: Cookies?.get('clients_country') || Cookies?.getJSON('website_status'), + user_language: Cookies?.get('user_language') || getLanguage(), device_language: navigator?.language || ' ', device_type: isMobile ? 'mobile' : 'desktop', + utm_source: utm_data?.['utm_source'], + utm_medium: utm_data?.['utm_medium'], + utm_campaign: utm_data?.['utm_campaign'], + is_authorised: !!Cookies?.get('client_information'), }) //datadog const dd_options = { diff --git a/gatsby-config.js b/gatsby-config.js index ee60d0462bc..ee1fd414729 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -391,15 +391,5 @@ module.exports = { collectionTypes: strapi_config, }, }, - { - resolve: 'gatsby-plugin-env-variables', - options: { - allowList: [ - 'GATSBY_RUDDERSTACK_URL', - 'GATSBY_RUDDERSTACK_STAGING_KEY', - 'GATSBY_RUDDERSTACK_PRODUCTION_KEY', - ], - }, - }, ], } diff --git a/gatsby-node.js b/gatsby-node.js index f9194b31a18..9611a724f77 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -428,25 +428,32 @@ exports.onCreateWebpackConfig = ({ stage, actions, loaders, getConfig }, { ...op const config = getConfig() const isProduction = config.mode === 'production' + const splitChunks = { + chunks: 'all', + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all', + priority: -10, + }, + bundle: { + test: /\.(js|ts|tsx)$/, + name: 'bundle', + chunks: 'all', + priority: -20, + enforce: true, + }, + }, + } + actions.setWebpackConfig({ devtool: isProduction ? false : 'inline-source-map', // enable/disable source-maps mode: isProduction ? 'production' : 'development', optimization: { minimize: isProduction, minimizer: [new TerserPlugin()], - splitChunks: { - chunks: 'all', - cacheGroups: { - default: false, - vendors: false, - // Merge all js, ts, and tsx files into one bundle - all: { - test: /\.(js|ts|tsx)$/, - name: 'bundle', - chunks: 'all', - }, - }, - }, + ...(isProduction && { splitChunks }), mangleExports: 'size', mangleWasmImports: true, diff --git a/i18n-config.js b/i18n-config.js index c158ef86644..f9d6dda89a8 100644 --- a/i18n-config.js +++ b/i18n-config.js @@ -45,7 +45,7 @@ module.exports = { }, th: { path: 'th', - display_name: 'Thai', + display_name: 'ไทย', short_name: 'TH', affiliate_lang: 12, }, diff --git a/package-lock.json b/package-lock.json index 3d8f2b60df1..87711b9bb5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@artsy/fresnel": "^6.2.1", "@builder.io/partytown": "^0.8.1", - "@deriv-com/analytics": "^1.4.10", + "@deriv-com/analytics": "^1.4.11", "@deriv-com/blocks": "^0.87.0", "@deriv-com/components": "^0.52.0", "@deriv-com/hooks": "^0.11.0", @@ -59,6 +59,7 @@ "i18next": "^21.10.0", "install": "^0.13.0", "js-cookie": "^2.2.1", + "lodash.isequal": "^4.5.0", "lottie-web": "^5.12.2", "match-sorter": "^6.3.1", "npm": "^9.9.2", @@ -108,6 +109,7 @@ "@testing-library/user-event": "^14.5.1", "@types/jest": "^29.5.10", "@types/js-cookie": "^3.0.6", + "@types/lodash.isequal": "^4.5.8", "@types/node": "^20.10.0", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", @@ -128,7 +130,6 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-webpack-plugin": "^3.2.0", - "gatsby-plugin-env-variables": "^2.3.0", "gatsby-plugin-eslint": "^4.0.4", "gatsby-plugin-postcss": "^6.12.0", "gatsby-plugin-styled-components": "^6.12.0", @@ -2793,9 +2794,9 @@ } }, "node_modules/@deriv-com/analytics": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/@deriv-com/analytics/-/analytics-1.4.10.tgz", - "integrity": "sha512-kZDrqhLzfL5DuWro/Pg1ePS4gPtUrXbGePH8c8yN/dejy0wsLgcQlr/ELnTkLZNi9RR2t1750vpIe1ZBh8dzqw==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@deriv-com/analytics/-/analytics-1.4.11.tgz", + "integrity": "sha512-8hyFfkwYZmiMVJchKW+d209t2NpNacjNw06jCSEnmpHyHhjpghOWVmKVGSTYG9T1WiMjzNz5Xq0Mx17mR7awXQ==", "dependencies": { "@growthbook/growthbook": "^0.29.0", "rudder-sdk-js": "^2.35.0" @@ -15558,6 +15559,15 @@ "version": "4.14.198", "license": "MIT" }, + "node_modules/@types/lodash.isequal": { + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.8.tgz", + "integrity": "sha512-uput6pg4E/tj2LGxCZo9+y27JNyB2OZuuI/T5F+ylVDYuqICLG2/ktjxx0v6GvVntAf8TvEzeQLcV0ffRirXuA==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/long": { "version": "4.0.2", "license": "MIT" @@ -25475,14 +25485,6 @@ "gatsby": "^5.0.0-next" } }, - "node_modules/gatsby-plugin-env-variables": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "gatsby": "^5.0.0 || ^4.0.0 || ^3.0.0 || ^2.0.0" - } - }, "node_modules/gatsby-plugin-eslint": { "version": "4.0.4", "dev": true, @@ -34114,6 +34116,11 @@ "version": "4.5.0", "license": "MIT" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.map": { "version": "4.6.0", "license": "MIT" diff --git a/package.json b/package.json index cba2dd03060..715e3c9aff2 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "@artsy/fresnel": "^6.2.1", "@builder.io/partytown": "^0.8.1", - "@deriv-com/analytics": "^1.4.10", + "@deriv-com/analytics": "^1.4.11", "@deriv-com/blocks": "^0.87.0", "@deriv-com/components": "^0.52.0", "@deriv-com/hooks": "^0.11.0", @@ -54,6 +54,7 @@ "i18next": "^21.10.0", "install": "^0.13.0", "js-cookie": "^2.2.1", + "lodash.isequal": "^4.5.0", "lottie-web": "^5.12.2", "match-sorter": "^6.3.1", "npm": "^9.9.2", @@ -103,6 +104,7 @@ "@testing-library/user-event": "^14.5.1", "@types/jest": "^29.5.10", "@types/js-cookie": "^3.0.6", + "@types/lodash.isequal": "^4.5.8", "@types/node": "^20.10.0", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", @@ -123,7 +125,6 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-webpack-plugin": "^3.2.0", - "gatsby-plugin-env-variables": "^2.3.0", "gatsby-plugin-eslint": "^4.0.4", "gatsby-plugin-postcss": "^6.12.0", "gatsby-plugin-styled-components": "^6.12.0", diff --git a/src/common/constants.ts b/src/common/constants.ts index a5c50ad08f4..589160c4e7f 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -166,7 +166,7 @@ export const localized_link_url = Object.freeze({ 'terms_and_conditions/#clients': domain_full_url, 'terms_and_conditions/#business-partners': domain_full_url, }) -export const default_server_url = 'green.binaryws.com' +export const default_server_url = 'green.derivws.com' export const live_chat_key = 'live_chat_redirection' diff --git a/src/common/country-base.ts b/src/common/country-base.ts index b0d7b707482..e10ae139670 100644 --- a/src/common/country-base.ts +++ b/src/common/country-base.ts @@ -134,7 +134,7 @@ export const african_countries = [ ] // special partnership payments for this countries -export const cpa_plan_countries = ['za', 'ec'] +export const cpa_plan_countries = ['za', 'ec', 'br', 'lk', 'uy'] export const isEuCountry = (clients_country: (typeof eu_countries)[number]): boolean => eu_countries.includes(clients_country) diff --git a/src/components/custom/other-platforms.tsx b/src/components/custom/other-platforms.tsx index 21438e007ca..1f2a09c934e 100644 --- a/src/components/custom/other-platforms.tsx +++ b/src/components/custom/other-platforms.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled, { css } from 'styled-components' import { Flex, FlexGridContainer, SectionContainer } from 'components/containers' import { Card, CardLink, Header, LocalizedLinkText, NavCard, Text } from 'components/elements' @@ -184,7 +184,7 @@ export const DMT5Card = ({ is_selected, is_ppc_redirect, word_break_cover }: DMT ( { const excludetoLowerCase = exclude.toLowerCase() const { is_row, is_eu } = useRegion() + const [header_text, setHeaderText] = useState('_t_Check out our other platforms_t_') + const [show_row_content, setShowRowContent] = useState(true) - const getHeaderText = () => ( - <> - {is_eu && } - {is_row && } - - ) + useEffect(() => { + if (is_eu) setHeaderText('_t_Check out our other platform_t_') + if (!is_row) setShowRowContent(false) + }, [is_eu, is_row]) return ( {is_nav ? null : (
- {header ? : getHeaderText()} + {header ? ( + + ) : ( + + )}
{subHeader && (
{excludetoLowerCase !== 'dtrader' && } - {is_row && <>{excludetoLowerCase !== 'dbot' && }} + {show_row_content && <>{excludetoLowerCase !== 'dbot' && }} {excludetoLowerCase !== 'dmt5' && } - {is_row && <>{excludetoLowerCase !== 'derivx' && }} + {show_row_content && <>{excludetoLowerCase !== 'derivx' && }} ) @@ -460,7 +464,7 @@ export const NavPlatform = ({ onClick, is_ppc, is_ppc_redirect }: NavPlatformPro /> )} content="_t_Trade multipliers on forex, cryptocurrencies, and synthetic indices with our mobile app._t_" - title='Deriv GO' + title="Deriv GO" onClick={onClick} to="/deriv-go/" /> diff --git a/src/components/elements/market-tab/index.tsx b/src/components/elements/market-tab/index.tsx index 08bc52c97a5..33889514115 100644 --- a/src/components/elements/market-tab/index.tsx +++ b/src/components/elements/market-tab/index.tsx @@ -65,7 +65,7 @@ const MarketTab = () => { ), )} - + ) diff --git a/src/components/elements/off-canvas-menu.tsx b/src/components/elements/off-canvas-menu.tsx index 4341c9bb174..d128cc11914 100644 --- a/src/components/elements/off-canvas-menu.tsx +++ b/src/components/elements/off-canvas-menu.tsx @@ -309,7 +309,7 @@ export const OffCanvasMenuWrapper = (props: OffCanvasMenuWrapperProps) => { /> )} content="_t_Trade multipliers on forex, cryptocurrencies, and synthetic indices with our mobile app._t_" - title='Deriv GO' + title="Deriv GO" onClick={handleArrowClick} to="/deriv-go/" /> diff --git a/src/components/hooks/use-auth-check.tsx b/src/components/hooks/use-auth-check.tsx index 4339ee3f149..3a9a1feb8dc 100644 --- a/src/components/hooks/use-auth-check.tsx +++ b/src/components/hooks/use-auth-check.tsx @@ -2,12 +2,13 @@ import { useEffect, useRef, useState } from 'react' import { isLoggedIn } from 'common/utility' const useAuthCheck = () => { - const [is_logged_in, setLoggedIn] = useState(isLoggedIn()) + const [is_logged_in, setLoggedIn] = useState(false) const [is_auth_checked, setIsAuthChecked] = useState(false) const checkCookieInterval = useRef() useEffect(() => { setIsAuthChecked(true) + setLoggedIn(isLoggedIn()) checkCookieInterval.current = setInterval(() => setLoggedIn(isLoggedIn()), 800) return () => clearInterval(checkCookieInterval.current) }, []) diff --git a/src/components/hooks/use-dynamic-visible-content.tsx b/src/components/hooks/use-dynamic-visible-content.tsx index 4eb590eb592..a53dbdb6636 100644 --- a/src/components/hooks/use-dynamic-visible-content.tsx +++ b/src/components/hooks/use-dynamic-visible-content.tsx @@ -1,4 +1,6 @@ -import { useMemo } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' +import isEqual from 'lodash.isequal' +import { useUpdateEffect } from 'usehooks-ts' import { ObjectPropType, TSmartContent } from 'types/generics' export interface IUseDynamicVisibleContent> { @@ -31,7 +33,23 @@ function useDynamicVisibleContent>({ return filterDynamicVisibleContent(content, config) }, [content, config]) - return visible_items + const prevVisibleItemsRef = useRef([]) + const [items, setItems] = useState([]) + + useEffect(() => { + setItems(visible_items) + prevVisibleItemsRef.current = visible_items + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + useUpdateEffect(() => { + if (!isEqual(prevVisibleItemsRef.current, visible_items)) { + setItems(visible_items) + prevVisibleItemsRef.current = visible_items + } + }, [visible_items]) + + return items } export default useDynamicVisibleContent diff --git a/src/components/hooks/use-handle-signup.tsx b/src/components/hooks/use-handle-signup.tsx index 637b62f47af..e46bb693b09 100644 --- a/src/components/hooks/use-handle-signup.tsx +++ b/src/components/hooks/use-handle-signup.tsx @@ -1,24 +1,20 @@ import { navigate, withPrefix } from 'gatsby' +import { Analytics } from '@deriv-com/analytics' import { getLanguage } from 'common/utility' import useRegion from 'components/hooks/use-region' -const useHandleSignup = (_is_ppc = false) => { +const useHandleSignup = (_is_ppc = false, is_tracked = false) => { const { is_region_loading } = useRegion() let current_language = getLanguage() + '/' const signUpPath = withPrefix('/') - if (getLanguage() === 'en') { - current_language = '' - } + if (getLanguage() === 'en') current_language = '' return () => { - if (is_region_loading) { - return - } else if (_is_ppc) { - navigate(`${signUpPath}${current_language}landing/signup/`) - } else { - navigate(`${signUpPath}${current_language}signup/`) - } + !is_tracked && Analytics?.trackEvent('deriv_com_homepage_cta', { action: 'click' }) + if (is_region_loading) return + else if (_is_ppc) navigate(`${signUpPath}${current_language}landing/signup/`) + else navigate(`${signUpPath}${current_language}signup/`) } } diff --git a/src/components/hooks/use-show-eu-content.ts b/src/components/hooks/use-show-eu-content.ts new file mode 100644 index 00000000000..7b7e1263151 --- /dev/null +++ b/src/components/hooks/use-show-eu-content.ts @@ -0,0 +1,13 @@ +import { useState, useEffect } from 'react' +import useRegion from './use-region' + +export const useShowEuContent = () => { + const { is_eu } = useRegion() + const [show_eu_content, setShowEuContent] = useState(false) + + useEffect(() => { + if (is_eu) setShowEuContent(true) + }, [is_eu]) + + return show_eu_content +} diff --git a/src/components/hooks/use-visible-content.tsx b/src/components/hooks/use-visible-content.tsx index d6c1c9e110d..06f204155b9 100644 --- a/src/components/hooks/use-visible-content.tsx +++ b/src/components/hooks/use-visible-content.tsx @@ -1,4 +1,6 @@ -import { useMemo } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' +import isEqual from 'lodash.isequal' +import { useUpdateEffect } from 'usehooks-ts' import { TSmartContent } from 'types/generics' export interface IUseVisibleContent> { @@ -27,7 +29,23 @@ function useVisibleContent>({ return filterVisibleContent(content, config) }, [content, config]) - return visible_items + const prevVisibleItemsRef = useRef([]) + const [items, setItems] = useState([]) + + useEffect(() => { + setItems(visible_items) + prevVisibleItemsRef.current = visible_items + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + useUpdateEffect(() => { + if (!isEqual(prevVisibleItemsRef.current, visible_items)) { + setItems(visible_items) + prevVisibleItemsRef.current = visible_items + } + }, [visible_items]) + + return items } export default useVisibleContent diff --git a/src/features/components/molecules/layout-overlay/cfd-warning-banner/desktop-text.tsx b/src/features/components/molecules/layout-overlay/cfd-warning-banner/desktop-text.tsx new file mode 100644 index 00000000000..932fb0c2324 --- /dev/null +++ b/src/features/components/molecules/layout-overlay/cfd-warning-banner/desktop-text.tsx @@ -0,0 +1,42 @@ +import React from 'react' +import * as styles from './cfd-warning-banner.module.scss' +import { Localize } from 'components/localization' +import Container from 'features/components/atoms/container' +import Link from 'features/components/atoms/link' +import Typography from 'features/components/atoms/typography' + +type TextProps = { + loss_percent: number +} + +const DesktopText = ({ loss_percent }: TextProps) => { + return ( + + + + , + ]} + /> + + + + ) +} + +export default DesktopText diff --git a/src/features/components/molecules/layout-overlay/cfd-warning-banner/index.tsx b/src/features/components/molecules/layout-overlay/cfd-warning-banner/index.tsx index d7905029fed..cf86d6d3aea 100644 --- a/src/features/components/molecules/layout-overlay/cfd-warning-banner/index.tsx +++ b/src/features/components/molecules/layout-overlay/cfd-warning-banner/index.tsx @@ -1,20 +1,13 @@ -import React, { useState } from 'react' +import React from 'react' import { graphql, useStaticQuery } from 'gatsby' -import * as styles from './cfd-warning-banner.module.scss' -import { Localize } from 'components/localization' -import Arrow from 'images/svg/arrow_expandable.svg' -import Container from 'features/components/atoms/container' -import Flex from 'features/components/atoms/flex-box' -import Link from 'features/components/atoms/link' -import Image from 'features/components/atoms/image' -import Typography from 'features/components/atoms/typography' +import MobileText from './mobile-text' +import DesktopText from './desktop-text' import useRegion from 'components/hooks/use-region' import usePpc from 'features/hooks/use-ppc' const CfdWarningBanner = () => { const { is_ppc } = usePpc() const { is_eu, is_cpa_plan } = useRegion() - const [expanded, setExpanded] = useState(false) const data = useStaticQuery(graphql` query { strapiCfdWarningBanner { @@ -23,93 +16,11 @@ const CfdWarningBanner = () => { } `) const loss_percent = data?.strapiCfdWarningBanner?.loss_percent - if (is_ppc || is_eu || is_cpa_plan) { - const toggleExpansion = () => { - setExpanded((prev) => !prev) - } - return ( <> - - - - {expanded ? ( - <> - , - ]} - /> - - ) : ( - - , - ]} - /> - - )} - - - - Expand - - - - - , - ]} - /> - - - + + ) } diff --git a/src/features/components/molecules/layout-overlay/cfd-warning-banner/mobile-text.tsx b/src/features/components/molecules/layout-overlay/cfd-warning-banner/mobile-text.tsx new file mode 100644 index 00000000000..7272eafdc64 --- /dev/null +++ b/src/features/components/molecules/layout-overlay/cfd-warning-banner/mobile-text.tsx @@ -0,0 +1,75 @@ +import React, { useState } from 'react' +import * as styles from './cfd-warning-banner.module.scss' +import { Localize } from 'components/localization' +import Arrow from 'images/svg/arrow_expandable.svg' +import Container from 'features/components/atoms/container' +import Flex from 'features/components/atoms/flex-box' +import Link from 'features/components/atoms/link' +import Image from 'features/components/atoms/image' +import Typography from 'features/components/atoms/typography' +import dclsx from 'features/utils/dclsx' + +type TextProps = { + loss_percent: number +} + +const MobileText = ({ loss_percent }: TextProps) => { + const [expanded, setExpanded] = useState(false) + const toggleExpansion = () => { + setExpanded((prev) => !prev) + } + return ( + + + {expanded ? ( + + , + ]} + /> + + ) : ( + + + , + ]} + /> + + + )} + + + Expand + + ) +} + +export default MobileText diff --git a/src/features/components/molecules/layout-overlay/index.tsx b/src/features/components/molecules/layout-overlay/index.tsx index 5fc842e2d46..68df3b275f4 100644 --- a/src/features/components/molecules/layout-overlay/index.tsx +++ b/src/features/components/molecules/layout-overlay/index.tsx @@ -1,17 +1,19 @@ -import React, { lazy, Suspense } from 'react' +import React from 'react' import pMinDelay from 'p-min-delay' import loadable from '@loadable/component' import { overlay_container } from './layout-overlay.module.scss' import CfdWarningBanner from './cfd-warning-banner' import Flex from 'features/components/atoms/flex-box' import { useIsRtl } from 'components/hooks/use-isrtl' +import { usePageLoaded } from 'components/hooks/use-page-loaded' const LiveChatButton = loadable(() => pMinDelay(import('./live-chat-button'), 5000)) const WhatsappButton = loadable(() => pMinDelay(import('./whats-app-button'), 5000)) -const CookieBanner = lazy(() => import('./cookie-banner')) +const CookieBanner = loadable(() => pMinDelay(import('./cookie-banner'), 5000)) const LayoutOverlay = () => { const is_rtl = useIsRtl() + const [is_mounted] = usePageLoaded() return ( { align="end" > - }> - - + - + {is_mounted && } ) } diff --git a/src/features/components/quill/layout-overlay/index.tsx b/src/features/components/quill/layout-overlay/index.tsx index 8875e233424..5f1eda0026c 100644 --- a/src/features/components/quill/layout-overlay/index.tsx +++ b/src/features/components/quill/layout-overlay/index.tsx @@ -1,4 +1,4 @@ -import React, { lazy, Suspense } from 'react' +import React from 'react' import clsx from 'clsx' import pMinDelay from 'p-min-delay' import loadable from '@loadable/component' @@ -6,10 +6,11 @@ import { wrapper_ltr, wrapper_rtl } from './styles.module.scss' import CfdWarningBanner from './cfd-warning-banner' import { useIsRtl } from 'components/hooks/use-isrtl' import { useFloatingCtaContext } from 'features/contexts/floating-cta/cta.provider' +import { usePageLoaded } from 'components/hooks/use-page-loaded' const LiveChatButton = loadable(() => pMinDelay(import('./live-chat-button'), 5000)) const WhatsappButton = loadable(() => pMinDelay(import('./whats-app-button'), 5000)) -const CookieBanner = lazy(() => import('./cookie-banner')) +const CookieBanner = loadable(() => pMinDelay(import('./cookie-banner'), 5000)) function calculatePercentageOfNumber(percentage: number, number: number) { const result = (percentage / 100) * number @@ -19,6 +20,7 @@ function calculatePercentageOfNumber(percentage: number, number: number) { const LayoutOverlay = () => { const is_rtl = useIsRtl() const { visibilityPercentage } = useFloatingCtaContext() + const [is_mounted] = usePageLoaded() return (
{ is_rtl ? 'justify-end' : 'justify-start', )} > - }> - - +
{
- + {is_mounted && } ) } diff --git a/src/features/components/templates/banners/award-banners/index.tsx b/src/features/components/templates/banners/award-banners/index.tsx index 2e462517f8b..8002778d93b 100644 --- a/src/features/components/templates/banners/award-banners/index.tsx +++ b/src/features/components/templates/banners/award-banners/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { awardImagesRow, awardImagesEu } from './data' +import { awardImagesRow } from './data' import { AwardProps } from './awardProps' import * as styles from './award-banner.module.scss' import Container from 'features/components/atoms/container' diff --git a/src/features/components/templates/footer/deriv-go-banner.tsx b/src/features/components/templates/footer/deriv-go-banner.tsx index 41421337d69..2f86fa29c57 100644 --- a/src/features/components/templates/footer/deriv-go-banner.tsx +++ b/src/features/components/templates/footer/deriv-go-banner.tsx @@ -1,18 +1,26 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { CaptionText, Heading, Text } from '@deriv/quill-design' // eslint-disable-next-line import/no-unresolved import { DerivProductDerivGoBrandLightLogoHorizontalIcon } from '@deriv/quill-icons/Logo' +import clsx from 'clsx' import DownloadBadges from './download' +import { footer_qr_box } from './styles.module.scss' import derivGoQR from 'images/common/migration/footer/deriv-go-qr.svg' import { Localize, localize } from 'components/localization' import useRegion from 'components/hooks/use-region' export const DerivGoBanner = () => { const { is_row } = useRegion() + const [show_content, setShowContent] = useState(true) + + useEffect(() => { + if (!is_row) setShowContent(false) + }, [is_row]) + const deriv_go = 'Deriv GO' return (
- {is_row && ( + {show_content && (
@@ -28,14 +36,19 @@ export const DerivGoBanner = () => {
-
+
{localize('_t_download - +
diff --git a/src/features/components/templates/footer/description.tsx b/src/features/components/templates/footer/description.tsx index 618b5ffbac6..9a2ae5d5bdf 100644 --- a/src/features/components/templates/footer/description.tsx +++ b/src/features/components/templates/footer/description.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { Text } from '@deriv/quill-design' import clsx from 'clsx' import { Localize } from 'components/localization' @@ -157,15 +157,12 @@ export const DescriptionContentCPA = () => { export const DescriptionContent = () => { const { is_eu, is_cpa_plan } = useRegion() const { exitRef } = useFloatingCtaContext() - return ( -
- {is_eu ? ( - - ) : is_cpa_plan ? ( - - ) : ( - - )} -
- ) + const [content, setContent] = useState() + + useEffect(() => { + if (is_eu) setContent() + if (is_cpa_plan) setContent() + }, [is_eu, is_cpa_plan]) + + return
{content}
} diff --git a/src/features/components/templates/footer/index.tsx b/src/features/components/templates/footer/index.tsx index 703fd40de9e..5cfc9fc24e8 100644 --- a/src/features/components/templates/footer/index.tsx +++ b/src/features/components/templates/footer/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react' import { Footer } from '@deriv-com/blocks' -import { qtMerge } from '@deriv/quill-design' +import { qtJoin } from '@deriv/quill-design' import { EuFooterNavData, RowFooterNavData, @@ -16,8 +16,11 @@ import useRegion from 'components/hooks/use-region' import { getLocationPathname } from 'common/utility' export const MainFooter = () => { - const [is_career, setIsCareer] = useState(false) const { is_eu, is_cpa_plan } = useRegion() + const [is_career, setIsCareer] = useState(false) + const [social_buttons, setSocialButtons] = useState(socialButtonsROW) + const [warn_text, setWarnText] = useState(warnText) + const [nav_data, setNavData] = useState(RowFooterNavData) useEffect(() => { const current_path = getLocationPathname() @@ -26,22 +29,23 @@ export const MainFooter = () => { setIsCareer(is_career_page) }, []) - const socialButtons = is_career - ? socialButtonsCareers - : is_eu - ? socialButtonsEU - : socialButtonsROW + useEffect(() => { + const region_buttons = is_eu ? socialButtonsEU : socialButtonsROW + setSocialButtons(is_career ? socialButtonsCareers : region_buttons) + if (is_eu) setNavData(EuFooterNavData) + setWarnText(!is_eu && !is_cpa_plan ? warnText : null) + }, [is_eu, is_cpa_plan, is_career]) return ( - + ) } diff --git a/src/features/components/templates/footer/styles.module.scss b/src/features/components/templates/footer/styles.module.scss new file mode 100644 index 00000000000..d9d42d932b7 --- /dev/null +++ b/src/features/components/templates/footer/styles.module.scss @@ -0,0 +1,6 @@ +.footer_qr_box{ + flex-direction: row; + @media (min-width: 1024px) { + flex-direction: column; + } +} \ No newline at end of file diff --git a/src/features/components/templates/layout/data.ts b/src/features/components/templates/layout/data.ts index 043f184b4f4..046a638baea 100644 --- a/src/features/components/templates/layout/data.ts +++ b/src/features/components/templates/layout/data.ts @@ -46,7 +46,7 @@ export const langItemsROW: LangItems = { }, th: { path: 'th', - displayName: 'Thai', + displayName: 'ไทย', shortName: 'TH', affiliateLang: 12, }, diff --git a/src/features/components/templates/navigation/main-nav/index.tsx b/src/features/components/templates/navigation/main-nav/index.tsx index b3a8a607c16..077a41f401f 100644 --- a/src/features/components/templates/navigation/main-nav/index.tsx +++ b/src/features/components/templates/navigation/main-nav/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { NavigationBlock } from '@deriv-com/blocks' import MainNavigationButtons from './nav.buttons' import MainNavigationLogo from './nav.logo' @@ -7,11 +7,17 @@ import useRegion from 'components/hooks/use-region' const MainRowNavigation = () => { const { is_eu } = useRegion() + const [items, setItems] = useState(mainRowNavItems) + + useEffect(() => { + if (is_eu) setItems(mainEuNavItems) + }, [is_eu]) + return ( ) } diff --git a/src/features/components/templates/navigation/main-nav/nav.buttons.scss b/src/features/components/templates/navigation/main-nav/nav.buttons.scss index 2c259da3e7f..83d78ee9345 100644 --- a/src/features/components/templates/navigation/main-nav/nav.buttons.scss +++ b/src/features/components/templates/navigation/main-nav/nav.buttons.scss @@ -1,7 +1,7 @@ .navbuttons { - &_tradershub--hidden, - &_login--hidden, - &_opendemo--hidden { - display: none; - } -} \ No newline at end of file + &_tradershub--hidden, + &_login--hidden, + &_opendemo--hidden { + display: none; + } + } \ No newline at end of file diff --git a/src/features/components/templates/navigation/main-nav/nav.buttons.tsx b/src/features/components/templates/navigation/main-nav/nav.buttons.tsx index 778cc62b31b..817ce950ba4 100644 --- a/src/features/components/templates/navigation/main-nav/nav.buttons.tsx +++ b/src/features/components/templates/navigation/main-nav/nav.buttons.tsx @@ -43,7 +43,6 @@ export const MainNavigationButtons = () => { > {`Trader's Hub`} - - - {/* for gatsby only, so gatsby rendered version have the script which immediately renders correct button while it's not impacting hydrated versions @@ -73,11 +70,10 @@ export const MainNavigationButtons = () => { so there would be visible delay if it would be in gatsby-ssr still there might be micro flickering, but it should be completely marginal if ever visible */} - {!isRealDevice && ( -
(function() { const isLoggedIn = document?.cookie.split(';').some(function(item) { return item.trim().startsWith('client_information='); }); @@ -94,10 +90,8 @@ export const MainNavigationButtons = () => { })(); `, - }} - >
- )} - + }} + >
) diff --git a/src/features/components/templates/navigation/partners-nav/index.tsx b/src/features/components/templates/navigation/partners-nav/index.tsx index dacfc236968..a8828736de0 100644 --- a/src/features/components/templates/navigation/partners-nav/index.tsx +++ b/src/features/components/templates/navigation/partners-nav/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { NavigationBlock } from '@deriv-com/blocks' // eslint-disable-next-line import/no-unresolved import { SubBrandDerivPartnersBrandLightIcon } from '@deriv/quill-icons/Logo' @@ -10,6 +10,11 @@ import useRegion from 'components/hooks/use-region' const PartnersNav = () => { const { is_eu } = useRegion() + const [items, setItems] = useState(partnersItems) + + useEffect(() => { + if (is_eu) setItems(partnersEUItems) + }, [is_eu]) return ( { )} - items={is_eu ? partnersEUItems : partnersItems} + items={items} /> ) } diff --git a/src/features/components/templates/navigation/partners-nav/nav.buttons.tsx b/src/features/components/templates/navigation/partners-nav/nav.buttons.tsx index ad85ba9fb79..39358ce91c0 100644 --- a/src/features/components/templates/navigation/partners-nav/nav.buttons.tsx +++ b/src/features/components/templates/navigation/partners-nav/nav.buttons.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react' +import React, { useEffect, useState } from 'react' import { MobileNavToggle } from '@deriv-com/blocks' import { Button } from '@deriv/quill-design' import { getLocationPathname } from 'common/utility' @@ -52,18 +52,21 @@ const PaymentAgentButtons = () => { const PartnersNavButtons = () => { const { is_eu } = useRegion() const path_name = getLocationPathname() + const [show_affiliate_btns, setShowAffiliateBtns] = useState(false) + const [show_payment_btns, setShowPaymentBtns] = useState(false) - const affiliate_buttons = useMemo(() => { - return !path_name ? null : path_name.includes('affiliate-ib') ? ( - - ) : path_name.includes('payment-agent') && !is_eu ? ( - - ) : null + useEffect(() => { + setShowAffiliateBtns(!path_name ? null : path_name.includes('affiliate-ib')) + }, [path_name]) + + useEffect(() => { + setShowPaymentBtns(path_name.includes('payment-agent') && !is_eu) }, [is_eu, path_name]) return (
- {affiliate_buttons} + {show_affiliate_btns && } + {show_payment_btns && }
) diff --git a/src/features/components/templates/navigation/partners-nav/prime-nav.tsx b/src/features/components/templates/navigation/partners-nav/prime-nav.tsx index 569c38ec846..3cc7d439d38 100644 --- a/src/features/components/templates/navigation/partners-nav/prime-nav.tsx +++ b/src/features/components/templates/navigation/partners-nav/prime-nav.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { MobileNavToggle, NavigationBlock } from '@deriv-com/blocks' // eslint-disable-next-line import/no-unresolved import { SubBrandDerivPrimeBrandLightIcon } from '@deriv/quill-icons/Logo' @@ -37,6 +37,12 @@ const PrimeNavButtons = () => { const PrimeNav = () => { const { is_eu } = useRegion() + const [items, setItems] = useState(partnersItems) + + useEffect(() => { + if (is_eu) setItems(partnersEUItems) + }, [is_eu]) + return ( { )} - items={is_eu ? partnersEUItems : partnersItems} + items={items} /> ) } diff --git a/src/features/components/templates/signup/with-banner/form/index.tsx b/src/features/components/templates/signup/with-banner/form/index.tsx index 4bb21e0ba66..a1210d8932d 100644 --- a/src/features/components/templates/signup/with-banner/form/index.tsx +++ b/src/features/components/templates/signup/with-banner/form/index.tsx @@ -1,6 +1,7 @@ import React from 'react' +import { Analytics } from '@deriv-com/analytics' import PublicSignupSocial from '../social' -import { signup_public_form_container, signup_public_form } from './form.module.scss' +import { signup_public_form, signup_public_form_container } from './form.module.scss' import Flex from 'features/components/atoms/flex-box' import Typography from 'features/components/atoms/typography' import { localize, Localize } from 'components/localization' @@ -9,11 +10,17 @@ import Link from 'features/components/atoms/link' import Input from 'features/components/atoms/input' import { TString } from 'types/generics' import useSignupForm from 'features/hooks/use-signup-form' +import { usePageLoaded } from 'components/hooks/use-page-loaded' + +const handleCTA = () => Analytics?.trackEvent('deriv_com_signup_cta', { action: 'click' }) const SignupPublicForm = () => { const { onSignup, signUpForm } = useSignupForm({ form_name: 'virtual_signup_homepage_embedded', }) + const [is_mounted] = usePageLoaded() + + if (!is_mounted) return null const { register, @@ -82,7 +89,7 @@ const SignupPublicForm = () => { /> - + diff --git a/src/features/hooks/use-signup-form/index.tsx b/src/features/hooks/use-signup-form/index.tsx index 2b7be0045c1..5223bb01e57 100644 --- a/src/features/hooks/use-signup-form/index.tsx +++ b/src/features/hooks/use-signup-form/index.tsx @@ -57,7 +57,7 @@ const useSignupForm = (options?: TSignupFormOptions) => { const onSignup = ({ email }: FormData) => { Analytics?.trackEvent('ce_virtual_signup_form', { - action: 'started', + action: 'email_confirmation_sent', signup_provider: 'email', ...analyticsData, }) diff --git a/src/features/hooks/use-states-list/index.tsx b/src/features/hooks/use-states-list/index.tsx index 4e51087e79a..9cb8affe4fd 100644 --- a/src/features/hooks/use-states-list/index.tsx +++ b/src/features/hooks/use-states-list/index.tsx @@ -12,8 +12,9 @@ const formatStatesList = (states) => { } return states?.map( - ({ text }) => + ({ text, value }) => typeof text !== undefined && { + symbol: value, name: text, display_name: text, }, diff --git a/src/features/pages/home/cta/index.tsx b/src/features/pages/home/cta/index.tsx index 9ce26421c62..8b1083fe21c 100644 --- a/src/features/pages/home/cta/index.tsx +++ b/src/features/pages/home/cta/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { Footer } from '@deriv-com/blocks' import { Heading } from '@deriv/quill-design' import { StaticImage } from 'gatsby-plugin-image' @@ -32,8 +32,14 @@ const EUImage = ( const CTA = () => { const { is_eu } = useRegion() + const [bg_image, setBgImage] = useState(RowImage) + + useEffect(() => { + if (is_eu) setBgImage(EUImage) + }, [is_eu]) + return ( - +
diff --git a/src/features/pages/home/data.ts b/src/features/pages/home/data.ts index 043f184b4f4..046a638baea 100644 --- a/src/features/pages/home/data.ts +++ b/src/features/pages/home/data.ts @@ -46,7 +46,7 @@ export const langItemsROW: LangItems = { }, th: { path: 'th', - displayName: 'Thai', + displayName: 'ไทย', shortName: 'TH', affiliateLang: 12, }, diff --git a/src/features/pages/home/index.tsx b/src/features/pages/home/index.tsx index 4017df7e16a..d521d72e230 100644 --- a/src/features/pages/home/index.tsx +++ b/src/features/pages/home/index.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import React, { lazy, Suspense } from 'react' +import React from 'react' +import loadable from '@loadable/component' import { PageLayout } from '@deriv-com/components' import QuillLayout from 'features/components/quill/quill-layout' import TwentyYearsStrong from './years' @@ -11,10 +12,10 @@ import TrustpilotSection from './trustpilot' import { useOpenLiveChat } from 'components/hooks/use-open-live-chat-redirection' import MainRowNavigation from 'features/components/templates/navigation/main-nav' import MainFooter from 'features/components/templates/footer' -const FastPaymentSection = lazy(() => import('./fast-payment')) -const LiveMarketSection = lazy(() => import('./live-pricing-migration')) -const TradeTypeSection = lazy(() => import('./trade-type')) -const UserFriendlyPlatforms = lazy(() => import('./user-platfroms')) +const FastPaymentSection = loadable(() => import('./fast-payment')) +const LiveMarketSection = loadable(() => import('./live-pricing-migration')) +const TradeTypeSection = loadable(() => import('./trade-type')) +const UserFriendlyPlatforms = loadable(() => import('./user-platfroms')) const HomePage = () => { useOpenLiveChat(true) @@ -27,19 +28,19 @@ const HomePage = () => { - }> - - - }> - - - }> - - + } + /> + } + /> + } + /> - }> - - + } + /> diff --git a/src/features/pages/home/live-pricing-migration/cards/index.tsx b/src/features/pages/home/live-pricing-migration/cards/index.tsx index fcadbc14d74..98bf92e541c 100644 --- a/src/features/pages/home/live-pricing-migration/cards/index.tsx +++ b/src/features/pages/home/live-pricing-migration/cards/index.tsx @@ -1,4 +1,5 @@ import React, { ReactNode, useMemo } from 'react' +import { Analytics } from '@deriv-com/analytics' import { CardSlider, LiveMarketContent } from '@deriv-com/components' import { MarketForexAudusdIcon, @@ -34,7 +35,7 @@ import { percentToDecimal, swiperOption } from '../utils' import { handleRedirectToTradersHub } from 'components/custom/utils' import useAuthCheck from 'components/hooks/use-auth-check' import useHandleSignup from 'components/hooks/use-handle-signup' -import { Localize, is_rtl } from 'components/localization' +import { is_rtl, Localize } from 'components/localization' const IconsMapper = { // Forex Icons @@ -88,7 +89,7 @@ const LiveMarketCard = ({ children: ReactNode }) => { const [is_logged_in] = useAuthCheck() - const handleSignup = useHandleSignup() + const handleSignup = useHandleSignup(false, true) const { data } = useLiveData(market) @@ -109,8 +110,26 @@ const LiveMarketCard = ({ askPrice: `${data[key].ask}`, spread: `${data[key].sprd}`, mid: data[key].mid, - onClickBuyButton: is_logged_in ? handleRedirectToTradersHub : handleSignup, - onClickSellButton: is_logged_in ? handleRedirectToTradersHub : handleSignup, + onClickBuyButton: is_logged_in + ? handleRedirectToTradersHub + : () => { + Analytics?.trackEvent('deriv_com_liveprice_cta', { + action: 'click', + button: 'buy', + instrument: data[key].sym, + }) + handleSignup() + }, + onClickSellButton: is_logged_in + ? handleRedirectToTradersHub + : () => { + Analytics?.trackEvent('deriv_com_liveprice_cta', { + action: 'click', + button: 'sell', + instrument: data[key].sym, + }) + handleSignup() + }, bidContent: , askContent: , spreadContent: , diff --git a/src/features/pages/home/start-trading-steps/index.tsx b/src/features/pages/home/start-trading-steps/index.tsx index 7ed59edc325..8fcb58ad80d 100644 --- a/src/features/pages/home/start-trading-steps/index.tsx +++ b/src/features/pages/home/start-trading-steps/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { Features } from '@deriv-com/blocks' import { EUCards, RowCards } from './data' import { Localize } from 'components/localization' @@ -7,6 +7,12 @@ import TradersHubCtaButton from 'features/components/molecules/traders-hub-cta-b const StartTradingSteps = () => { const { is_eu } = useRegion() + const [cards, setCards] = useState(RowCards) + + useEffect(() => { + if (is_eu) setCards(EUCards) + }, [is_eu]) + return ( { } cols="three" variant="ContentTop" - cards={is_eu ? EUCards : RowCards} + cards={cards} /> ) } diff --git a/src/features/pages/markets/etf/index.tsx b/src/features/pages/markets/etf/index.tsx index f5cbb8ff11b..2a753bcb932 100644 --- a/src/features/pages/markets/etf/index.tsx +++ b/src/features/pages/markets/etf/index.tsx @@ -10,10 +10,10 @@ import CheckTrading from './check-trading' import SignupPublic from 'features/components/templates/signup/with-banner' import Flex from 'features/components/atoms/flex-box' import OtherMarketsSlider from 'features/components/molecules/other-markets-slider' -import MainFooter from 'features/components/templates/footer/' import MainRowNavigation from 'features/components/templates/navigation/main-nav' import { usePlatformQueryParam } from 'components/hooks/use-platform-query-param' import MarketBottomNav from 'features/components/templates/navigation/template/market-bottom-nav' +import MainFooter from 'features/components/templates/footer' const ETFMarket = () => { const { is_deriv_go } = usePlatformQueryParam() diff --git a/src/features/pages/partners/deriv-prime/get-in-touch/contact-form.tsx b/src/features/pages/partners/deriv-prime/get-in-touch/contact-form.tsx index 54b0b8ca57c..33dfb97cd04 100644 --- a/src/features/pages/partners/deriv-prime/get-in-touch/contact-form.tsx +++ b/src/features/pages/partners/deriv-prime/get-in-touch/contact-form.tsx @@ -8,11 +8,9 @@ import Input from 'features/components/atoms/input' import { TString } from 'types/generics' import useContactForm from 'features/hooks/use-contact-form' import { TTypographyColor } from 'features/types' -import useBreakpoints from 'components/hooks/use-breakpoints' const ContactFormGetInTouch = () => { const { contact_us_form, on_submit, form_state } = useContactForm() - const { is_mobile } = useBreakpoints() const { register, diff --git a/src/features/pages/partners/deriv-prime/index.tsx b/src/features/pages/partners/deriv-prime/index.tsx index f9ddbadbe73..f7bb09629e6 100644 --- a/src/features/pages/partners/deriv-prime/index.tsx +++ b/src/features/pages/partners/deriv-prime/index.tsx @@ -10,8 +10,8 @@ import MeetUsThere from './meet-us-there' import ConnectivityReliabilityType from './connectivity-reliability' import AvailableInstruments from './available-instruments' import Hero from './hero' -import MainFooter from 'features/components/templates/footer' import PrimeNav from 'features/components/templates/navigation/partners-nav/prime-nav' +import MainFooter from 'features/components/templates/footer' const DerivPrime = () => { return ( diff --git a/src/features/pages/signup/form-container/signup-page-form.tsx b/src/features/pages/signup/form-container/signup-page-form.tsx index ec292fbdbe9..123a0e9fa93 100644 --- a/src/features/pages/signup/form-container/signup-page-form.tsx +++ b/src/features/pages/signup/form-container/signup-page-form.tsx @@ -7,9 +7,11 @@ import { localize, Localize } from 'components/localization' import Input from 'features/components/atoms/input' import Link from 'features/components/atoms/link' import useSignupForm from 'features/hooks/use-signup-form' +import { usePageLoaded } from 'components/hooks/use-page-loaded' const SignUpPageForm = () => { const { onSignup, signUpForm } = useSignupForm() + const [is_mounted] = usePageLoaded() const { register, @@ -24,6 +26,8 @@ const SignUpPageForm = () => { const is_button_disabled = values.email === '' || !values.terms || !isValid || isSubmitting || isSubmitSuccessful + if (!is_mounted) return null + return ( - - - - - - - - - - - - - - - - - - diff --git a/src/images/svg/trade-types/favourite.svg b/src/images/svg/trade-types/favourite.svg deleted file mode 100644 index b40a6fd0c00..00000000000 --- a/src/images/svg/trade-types/favourite.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/images/svg/trade-types/flexible.svg b/src/images/svg/trade-types/flexible.svg deleted file mode 100644 index 1c1a42ab202..00000000000 --- a/src/images/svg/trade-types/flexible.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/images/svg/trade-types/get-quote.svg b/src/images/svg/trade-types/get-quote.svg deleted file mode 100644 index 2c134fb2a06..00000000000 --- a/src/images/svg/trade-types/get-quote.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/images/svg/trade-types/instant.svg b/src/images/svg/trade-types/instant.svg deleted file mode 100644 index 9f63837223b..00000000000 --- a/src/images/svg/trade-types/instant.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/images/svg/trade-types/user-friendly.svg b/src/images/svg/trade-types/user-friendly.svg deleted file mode 100644 index 390f3faa91d..00000000000 --- a/src/images/svg/trade-types/user-friendly.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/pages/deriv-go/_banner.tsx b/src/pages/deriv-go/_banner.tsx index 1f7d18d67b3..fbca4d701b3 100644 --- a/src/pages/deriv-go/_banner.tsx +++ b/src/pages/deriv-go/_banner.tsx @@ -117,7 +117,7 @@ const DHero = () => { - + { secondColumnMobileMargin="8rem 0 0 0" > - Deriv Go + Deriv Go { mobilePadding="40px 0 10px" > - Deriv MT5 + Deriv MT5 { const { is_eu } = useRegion() - const contents = is_eu ? numbers_content_eu : numbers_content + const [contents, setContents] = useState(numbers_content) + + useEffect(() => { + if (is_eu) setContents(numbers_content_eu) + }, [is_eu]) return } diff --git a/src/pages/endpoint/index.tsx b/src/pages/endpoint/index.tsx index 740a4e28d4e..158d2285fa2 100644 --- a/src/pages/endpoint/index.tsx +++ b/src/pages/endpoint/index.tsx @@ -195,7 +195,7 @@ const Endpoint = () => { type="text" label="Server URL" background="white" - placeholder={'e.g. green.binaryws.com'} + placeholder="e.g. green.derivws.com" /> { const filtered_data = useFilteredCategory(data) + const [is_mounted] = usePageLoaded() + + if (!is_mounted) return null return (
diff --git a/src/pages/help-centre/components/_questions-template.tsx b/src/pages/help-centre/components/_questions-template.tsx index d10b48932e8..c08ba62323f 100644 --- a/src/pages/help-centre/components/_questions-template.tsx +++ b/src/pages/help-centre/components/_questions-template.tsx @@ -12,6 +12,7 @@ import { StyledLink } from 'components/elements' import { Container } from 'components/containers' import { usePlatformQueryParam } from 'components/hooks/use-platform-query-param' import { useIsRtl } from 'components/hooks/use-isrtl' +import { usePageLoaded } from 'components/hooks/use-page-loaded' type TQuestionsTemplate = { data: TQuestionsData @@ -28,11 +29,14 @@ const QuestionsTemplate = ({ data }: TQuestionsTemplate) => { const filtered_questions = useFilteredQuestions(questions) const { is_deriv_go } = usePlatformQueryParam() const { is_eu } = useRegion() + const [is_mounted] = usePageLoaded() React.useEffect(() => { window.scrollTo(0, 0) }, []) + if (!is_mounted) return null + return ( diff --git a/src/pages/help-centre/data/_hooks.tsx b/src/pages/help-centre/data/_hooks.tsx index 2221b9b6e0e..a0c7fc20f58 100644 --- a/src/pages/help-centre/data/_hooks.tsx +++ b/src/pages/help-centre/data/_hooks.tsx @@ -1,6 +1,8 @@ import { TQuestions, TQuestionsData } from './_data-types' import useRegion from 'components/hooks/use-region' +// TODO: Need to update these hooks and the questions data structue + export const useFilteredQuestions = (data: TQuestions[]) => { const { is_eu } = useRegion() return data.filter(({ hide_for_eu, hide_for_non_eu }) => diff --git a/src/pages/home/_data.ts b/src/pages/home/_data.ts deleted file mode 100644 index 9e8da6ce5e1..00000000000 --- a/src/pages/home/_data.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { TContent, THeaderItem } from './_types' - -export const header_items: THeaderItem[] = [ - { id: 0, text: '_t_Simple._t_' }, - { id: 1, text: '_t_Flexible._t_' }, - { id: 2, text: '_t_Reliable._t_' }, -] - -export const contents: TContent[] = [ - { id: 0, text: '_t_Tight spreads_t_' }, - { id: 1, text: '_t_Sharp prices_t_' }, - { id: 2, text: '_t_24x7 trading_t_' }, - { id: 3, text: '_t_100+ tradeable assets_t_' }, - { id: 4, text: '_t_20+ years of experience_t_' }, -] - -export const contents_ppc: TContent[] = [ - { id: 3, text: '_t_Tight spreads_t_' }, - { id: 2, text: '_t_Sharp prices_t_' }, - { id: 1, text: '_t_100+ tradeable assets_t_' }, - { id: 0, text: '_t_20+ years of experience_t_' }, -] diff --git a/src/pages/home/_data.tsx b/src/pages/home/_data.tsx new file mode 100644 index 00000000000..a25e289d137 --- /dev/null +++ b/src/pages/home/_data.tsx @@ -0,0 +1,105 @@ +import React from 'react' +import { StaticImage } from 'gatsby-plugin-image' +import { TContent, THeaderItem } from './_types' +import { localize } from 'components/localization' + +export const header_items: THeaderItem[] = [ + { id: 0, text: '_t_Simple._t_' }, + { id: 1, text: '_t_Flexible._t_' }, + { id: 2, text: '_t_Reliable._t_' }, +] + +export const contents: TContent[] = [ + { id: 0, text: '_t_Tight spreads_t_' }, + { id: 1, text: '_t_Sharp prices_t_' }, + { id: 2, text: '_t_24x7 trading_t_' }, + { id: 3, text: '_t_100+ tradeable assets_t_' }, + { id: 4, text: '_t_20+ years of experience_t_' }, +] + +export const contents_ppc: TContent[] = [ + { id: 3, text: '_t_Tight spreads_t_' }, + { id: 2, text: '_t_Sharp prices_t_' }, + { id: 1, text: '_t_100+ tradeable assets_t_' }, + { id: 0, text: '_t_20+ years of experience_t_' }, +] + +export const row_images = [ + { + key: 'hero1', + image: ( + + ), + }, + { + key: 'hero2', + image: ( + + ), + }, + { + key: 'hero3', + image: ( + + ), + }, + { + key: 'hero4', + image: ( + + ), + }, +] + +export const eu_images = [ + { + key: 'hero1_eu', + image: ( + + ), + }, + { + key: 'hero2_eu', + image: ( + + ), + }, +] diff --git a/src/pages/home/_hero.tsx b/src/pages/home/_hero.tsx index 42ca2619711..03336a39b8e 100644 --- a/src/pages/home/_hero.tsx +++ b/src/pages/home/_hero.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { StaticImage } from 'gatsby-plugin-image' import VerticalCarousel from './_vertical-carousel' @@ -65,9 +65,14 @@ const HeroHeader = ({ text }: { text: TString }) => { } const Hero = ({ is_ppc }: HeroProps) => { - const { is_region_loading, is_eu, is_row } = useRegion() + const { is_region_loading, is_eu } = useRegion() const [is_logged_in, is_auth_checked] = useAuthCheck() const handleSignup = useHandleSignup() + const [show_eu_content, setShowEuContent] = useState(false) + + useEffect(() => { + if (is_eu) setShowEuContent(true) + }, [is_eu]) return ( @@ -134,10 +139,10 @@ const Hero = ({ is_ppc }: HeroProps) => { min_height="auto" weight="normal" > - {is_eu && ( + {show_eu_content && ( )} - {is_row && ( + {!show_eu_content && ( )}
diff --git a/src/pages/home/_platform-slideshow.tsx b/src/pages/home/_platform-slideshow.tsx index e01998370b2..1f8cecfc0e8 100644 --- a/src/pages/home/_platform-slideshow.tsx +++ b/src/pages/home/_platform-slideshow.tsx @@ -1,10 +1,9 @@ -import React, { useState, useEffect, useMemo, useRef, ReactNode } from 'react' +import React, { useState, useEffect, useRef, ReactNode } from 'react' import styled from 'styled-components' -import { StaticImage } from 'gatsby-plugin-image' +import { eu_images, row_images } from './_data' import { Flex } from 'components/containers' import device from 'themes/device' import useRegion from 'components/hooks/use-region' -import { localize } from 'components/localization' const ImagePlaceHolder = styled.div` width: 690px; @@ -37,91 +36,12 @@ const SlideContainer = styled(Flex)` const PlatformSlideshow = () => { const [active_index, setActiveIndex] = useState(0) - const { is_row, is_eu, is_region_loading } = useRegion() - - const slide_images = useMemo(() => { - if (is_row) - return [ - { - key: 'hero1', - image: ( - - ), - }, - { - key: 'hero2', - image: ( - - ), - }, - { - key: 'hero3', - image: ( - - ), - }, - { - key: 'hero4', - image: ( - - ), - }, - ] - - if (is_eu) - return [ - { - key: 'hero1_eu', - image: ( - - ), - }, - { - key: 'hero2_eu', - image: ( - - ), - }, - ] - }, [is_eu, is_row]) + const { is_eu, is_region_loading } = useRegion() + const [slide_images, setSlideImages] = useState(row_images) + + useEffect(() => { + if (is_eu) setSlideImages(eu_images) + }, [is_eu]) const intervalRef = useRef(null) diff --git a/src/pages/home/_trade.tsx b/src/pages/home/_trade.tsx index a46cebd9df9..efb3bf1680f 100644 --- a/src/pages/home/_trade.tsx +++ b/src/pages/home/_trade.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { graphql, useStaticQuery } from 'gatsby' import { TraderCard, BotCard, DMT5Card } from 'components/custom/other-platforms' @@ -55,7 +55,12 @@ const Trade = ({ is_ppc_redirect }: TradeProps) => { const { is_non_eu } = useRegion() const data = useStaticQuery(query) // one option always has to be selected - const [selected, setSelected] = React.useState(null) + const [selected, setSelected] = useState(null) + const [show_non_eu_content, setShowNonEuContent] = useState(true) + + useEffect(() => { + if (!is_non_eu) setShowNonEuContent(false) + }, [is_non_eu]) return ( @@ -103,7 +108,7 @@ const Trade = ({ is_ppc_redirect }: TradeProps) => { > - {is_non_eu && ( + {show_non_eu_content && (
setSelected(platforms.bot)} onMouseLeave={() => setSelected('')} diff --git a/src/pages/landing/dmt5/index.tsx b/src/pages/landing/dmt5/index.tsx index 564dc67db3d..b94c65eef03 100644 --- a/src/pages/landing/dmt5/index.tsx +++ b/src/pages/landing/dmt5/index.tsx @@ -26,14 +26,17 @@ const query = graphql` const DMT5 = () => { const [is_mobile, setMobile] = useState(false) - const handleResizeWindow = () => { - setMobile(isBrowser() ? window.screen.width <= size.mobileL : false) - } useEffect(() => { - setMobile(isBrowser() ? window.screen.width <= size.mobileL : false) + const handleResizeWindow = () => { + setMobile(isBrowser() ? window.screen.width <= size.mobileL : false) + } window.addEventListener('resize', handleResizeWindow) - }) + + return () => { + window.removeEventListener('resize', handleResizeWindow) + } + }, []) const data = useStaticQuery(query) return ( diff --git a/src/pages/landing/forex-trading/components/_table-btn.tsx b/src/pages/landing/forex-trading/components/_table-btn.tsx index 21aa82e27cd..fa79a40adae 100644 --- a/src/pages/landing/forex-trading/components/_table-btn.tsx +++ b/src/pages/landing/forex-trading/components/_table-btn.tsx @@ -55,7 +55,7 @@ const Tablebtn = ({ btnlabel, text }: TablebtnProps) => { { id: 'swap-free-pairs', title: '_t_Swap-free pairs_t_', - component: , + instruments: , }, ], } diff --git a/src/pages/landing/trade-forex/components/_table-btn.tsx b/src/pages/landing/trade-forex/components/_table-btn.tsx index b2f967269d2..78b316cbdad 100644 --- a/src/pages/landing/trade-forex/components/_table-btn.tsx +++ b/src/pages/landing/trade-forex/components/_table-btn.tsx @@ -54,7 +54,7 @@ const swap_free_pairs: TMarketContent = { { id: 'swap-free-pairs', title: '_t_Swap-free pairs_t_', - component: , + instruments: , }, ], } diff --git a/src/pages/markets/commodities/index.tsx b/src/pages/markets/commodities/index.tsx index 2856f802c32..58072033577 100644 --- a/src/pages/markets/commodities/index.tsx +++ b/src/pages/markets/commodities/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import Commodities from '../components/markets/_commodities' import { DerivedFXHero } from '../components/sections/_hero_derived_fx' import { simple_step_content_commodities } from '../static/content/_commodities' @@ -8,21 +8,24 @@ import { WithIntl } from 'components/localization' import { SEO } from 'components/containers' import useRegion from 'components/hooks/use-region' import { TGatsbyHead } from 'features/types' +import { TString } from 'types/generics' const CommoditiesPage = () => { - const { is_row } = useRegion() + const { is_eu } = useRegion() + const [description, setDescription] = useState( + '_t_Trade popular assets in the commodities market such as silver, gold, oil, and more without owning the underlying asset. Speculate on the price movements and benefit from our high leverage and competitive spreads._t_', + ) - const hero_description = is_row - ? '_t_Trade popular assets in the commodities market such as silver, gold, oil, and more without owning the underlying asset. Speculate on the price movements and benefit from our high leverage and competitive spreads._t_' - : '_t_Trade popular assets in the commodities market such as silver, gold, oil, and more without owning the underlying asset. Speculate on the price movements and benefit from our competitive spreads._t_' + useEffect(() => { + if (is_eu) + setDescription( + '_t_Trade popular assets in the commodities market such as silver, gold, oil, and more without owning the underlying asset. Speculate on the price movements and benefit from our competitive spreads._t_', + ) + }, [is_eu]) return ( - + diff --git a/src/pages/markets/components/helper/_available-platforms.tsx b/src/pages/markets/components/helper/_available-platforms.tsx index 9a9f7051fec..e66b8ac85e2 100644 --- a/src/pages/markets/components/helper/_available-platforms.tsx +++ b/src/pages/markets/components/helper/_available-platforms.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { smarttrader_url } from 'common/constants' import DerivcTrader from 'images/svg/trading-platforms/ctrader/ctrader-main-logo.svg' @@ -94,9 +94,13 @@ const AvailablePlatforms = ({ m_top, }: AvailablePlatformsProps) => { const { is_eu } = useRegion() - const deriv_mt5_name: String = 'Deriv MT5' - const deriv_go_name: String = 'Deriv GO' - + const [show_derivx, setShowDerivX] = useState(true) + + useEffect(() => { + if (is_eu) setShowDerivX(false) + }, [is_eu]) + const deriv_mt5_name = 'Deriv MT5' + const deriv_go_name = 'Deriv GO' return ( - - {deriv_mt5_name} - + {deriv_mt5_name} )} @@ -156,7 +158,7 @@ const AvailablePlatforms = ({ )} - {derivx && !is_eu && ( + {derivx && show_derivx && ( @@ -170,9 +172,7 @@ const AvailablePlatforms = ({ - - {deriv_go_name} - + {deriv_go_name} )} diff --git a/src/pages/markets/components/helper/_available-trades_desktop.tsx b/src/pages/markets/components/helper/_available-trades_desktop.tsx index fb1f59cffb1..e8b9fe01195 100644 --- a/src/pages/markets/components/helper/_available-trades_desktop.tsx +++ b/src/pages/markets/components/helper/_available-trades_desktop.tsx @@ -201,13 +201,19 @@ const AvailableTradesDesktop = ({ Multipliers, display_title, }: AvailableTradesProps) => { - const { is_non_eu } = useRegion() - const params = new URLSearchParams(isBrowser() && location.search) + const { is_eu } = useRegion() const [tab, setTab] = useState('cfds') + const params = new URLSearchParams(isBrowser() && location.search) + const [show_digital_options, setShowDigitalOptions] = useState(true) + useEffect(() => { setTab(params.get('tab') || 'cfds') }, [params]) + useEffect(() => { + if (is_eu) setShowDigitalOptions(false) + }, [is_eu]) + const { is_deriv_go } = usePlatformQueryParam() return ( @@ -224,7 +230,7 @@ const AvailableTradesDesktop = ({ )} - {is_non_eu && DigitalOptions && ( + {show_digital_options && DigitalOptions && ( { const { is_eu } = useRegion() + const [show_digital_options, setShowDigitalOptions] = useState(true) + + useEffect(() => { + if (is_eu) setShowDigitalOptions(false) + }, [is_eu]) simple_step_content[1].text = '_t_Open a real account, make a deposit, and start trading commodities and other markets. _t_' return ( <> - {is_eu ? ( - } - display_title="_t_Commodity trades available on Deriv_t_" - /> - ) : ( - } - DigitalOptions={ + } + DigitalOptions={ + show_digital_options && ( - } - display_title="_t_Commodity trades available on Deriv_t_" - /> - )} + ) + } + display_title="_t_Commodity trades available on Deriv_t_" + /> import('components/custom/_simple-steps')) @@ -27,32 +29,65 @@ type CryptocurrenciesProps = { simple_step_content: TSimpleStepContent[] } -const Cryptocurrencies = ({ simple_step_content }: CryptocurrenciesProps) => { - const { is_eu } = useRegion() - const { is_deriv_go } = usePlatformQueryParam() +type MarketConfig = { + is_eu: boolean +} - const crypto_content: TMarket[] = [ - { +type SmartMarketItem = TSmartContent + +const crypto_content: SmartMarketItem[] = [ + { + id: 0, + data: { + src: Leverage, + text: '_t_1:100 leverage_t_', + alt: '_t_1 to 100 leverage_t_', + }, + visibility: { + is_eu: false, + }, + }, + { + id: 1, + data: { src: Leverage, - text: is_eu ? '_t_1:2 leverage_t_' : '_t_1:100 leverage_t_', + text: '_t_1:2 leverage_t_', alt: '_t_1 to 100 leverage_t_', }, - { + visibility: { + is_eu: true, + }, + }, + { + id: 2, + data: { src: TightSpread, text: '_t_Tight spreads_t_', alt: '_t_tight spreads_t_', }, - { + }, + { + id: 3, + data: { src: CryptoPairs, text: '_t_30+ crypto pairs_t_', alt: '_t_Crypto currency pairs_t_', }, - { + }, + { + id: 4, + data: { src: ZeroCommission, text: '_t_Zero commission_t_', alt: '_t_zero commission_t_', }, - ] + }, +] + +const Cryptocurrencies = ({ simple_step_content }: CryptocurrenciesProps) => { + const { is_eu } = useRegion() + const { is_deriv_go } = usePlatformQueryParam() + const visible_items = useVisibleContent({ content: crypto_content, config: { is_eu } }) return ( <> @@ -84,11 +119,18 @@ const Cryptocurrencies = ({ simple_step_content }: CryptocurrenciesProps) => { - {crypto_content.map(({ alt, src, text }) => ( + {visible_items.map((item) => ( } + key={item.id} + text={item.data.text} + icon={ + {localize(item.data.alt)} + } > ))} diff --git a/src/pages/markets/components/markets/_forex.tsx b/src/pages/markets/components/markets/_forex.tsx index 5d62e78a754..49b808aa90d 100644 --- a/src/pages/markets/components/markets/_forex.tsx +++ b/src/pages/markets/components/markets/_forex.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import Loadable from '@loadable/component' import AvailableTrades from '../helper/_available-trades' import { forex_content, forex_content_eu } from '../../static/content/_forex' @@ -26,18 +26,31 @@ type ForexProps = { } const Forex = ({ simple_step_content }: ForexProps) => { - const { is_row, is_eu } = useRegion() + const { is_eu } = useRegion() + const [content, setContent] = useState(forex_content) + const [cfds, setCfds] = useState(forex_cfds) + const [show_digital_options, setShowDigitalOptions] = useState(true) + const [multiplier, setMultiplier] = useState(forex_multiplier) + + useEffect(() => { + if (is_eu) { + setContent(forex_content_eu) + setCfds(forex_cfds_eu) + setShowDigitalOptions(false) + setMultiplier(forex_multiplier_eu) + } + }, [is_eu]) return ( <> } + CFDs={} DigitalOptions={ - is_row && - } - Multipliers={ - + show_digital_options && ( + + ) } + Multipliers={} display_title="_t_Forex trades available on Deriv_t_" /> { - {(is_eu ? forex_content_eu : forex_content).map(({ alt, src, text }) => ( + {content.map(({ alt, src, text }) => ( { const { is_eu } = useRegion() const { is_deriv_go } = usePlatformQueryParam() + const [cfds, setCfds] = useState(synthetic_cfds) + const [multiplier, setMultiplier] = useState(synthetic_multiplier) + + useEffect(() => { + if (is_eu) { + setCfds(synthetic_cfds_eu) + setMultiplier(synthetic_multiplier_eu) + } + }, [is_eu]) return (
} + CFDs={} DigitalOptions={ } - Multipliers={ - - } + Multipliers={} display_title="_t_Synthetics trades available on Deriv_t_" /> {content?.map( ({ - component, + instruments, title, col, details, @@ -52,7 +52,6 @@ const MarketInstruments = ({ /> - {template == 2 ? ( - {component} + {instruments} ) : template == 3 ? ( - {component} + {instruments} ) : ( - {component} + {instruments} )} )} @@ -98,11 +97,11 @@ const MarketInstruments = ({ gap_mobile={gap_mobile} {...markets_list} > - {component} + {instruments} ) : ( - {component} + {instruments} )} diff --git a/src/pages/markets/components/sections/_nav-tab.tsx b/src/pages/markets/components/sections/_nav-tab.tsx index 74522eab350..d3457a0889a 100644 --- a/src/pages/markets/components/sections/_nav-tab.tsx +++ b/src/pages/markets/components/sections/_nav-tab.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from 'react' +import React, { useEffect, useRef, useState } from 'react' import styled, { css } from 'styled-components' import { Text } from 'components/elements' import { Flex } from 'components/containers' @@ -123,12 +123,17 @@ const NavTab = ({ route_from }: TNavTab) => { const { is_eu } = useRegion() const ref = useRef(null) const { is_deriv_go } = usePlatformQueryParam() + const [tabs, setTabs] = useState(tab_list) + + useEffect(() => { + if (is_eu) setTabs(tab_list_eu) + }, [is_eu]) return ( {!is_deriv_go && ( - {(is_eu ? tab_list_eu : tab_list).map(({ route_to, tab_name, title }) => { + {tabs.map(({ route_to, tab_name, title }) => { return ( diff --git a/src/pages/markets/components/sub-markets/_cfds.tsx b/src/pages/markets/components/sub-markets/_cfds.tsx index 46a1714dee9..58aea9c649e 100644 --- a/src/pages/markets/components/sub-markets/_cfds.tsx +++ b/src/pages/markets/components/sub-markets/_cfds.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled from 'styled-components' import AvailablePlatforms from '../helper/_available-platforms' import { ContentWrapper, Descriptions, StyledText } from '../../static/style/_markets-style' @@ -9,6 +9,7 @@ import device from 'themes/device' import useRegion from 'components/hooks/use-region' import { Header } from 'components/elements' import { TMarketContent } from 'pages/markets/static/content/_types' +import { TString } from 'types/generics' type CFDProps = { market_content: TMarketContent @@ -23,31 +24,55 @@ const StyledHeader = styled(Header)` margin-top: 0.8rem; ` +interface TextsType { + first: TString + second: TString +} + const CFDs = ({ market_content }: CFDProps) => { const { is_eu } = useRegion() - const first_text = is_eu - ? '_t_CFD trading allows you to make a potential profit from the price movement of the underlying asset without purchasing it._t_' - : '_t_CFD trading allows you to trade on the price movement of an asset without buying or owning the underlying asset._t_' - const second_text = is_eu - ? '_t_On Deriv, trading CFDs on leverage lets you pay only a small fraction of the contract’s value and amplify your potential profit, similarly increasing your potential loss._t_' - : '_t_On Deriv, you can trade CFDs with high leverage, enabling you to pay just a fraction of the contract’s value. It will amplify your potential gain and also increase your potential loss._t_' + const [texts, setTexts] = useState({ + first: '_t_CFD trading allows you to trade on the price movement of an asset without buying or owning the underlying asset._t_', + second: '_t_On Deriv, you can trade CFDs with high leverage, enabling you to pay just a fraction of the contract’s value. It will amplify your potential gain and also increase your potential loss._t_', + }) + const [platforms, setPlatforms] = useState({ + dmt5: true, + derivx: true, + deriv_ez: true, + deriv_ctrader: true, + }) + + useEffect(() => { + if (is_eu) { + setTexts({ + first: '_t_CFD trading allows you to make a potential profit from the price movement of the underlying asset without purchasing it._t_', + second: '_t_On Deriv, trading CFDs on leverage lets you pay only a small fraction of the contract’s value and amplify your potential profit, similarly increasing your potential loss._t_', + }) + setPlatforms({ + dmt5: true, + derivx: false, + deriv_ez: false, + deriv_ctrader: false, + }) + } + }, [is_eu]) return ( - + - + diff --git a/src/pages/markets/components/sub-markets/_multipliers.tsx b/src/pages/markets/components/sub-markets/_multipliers.tsx index 8da816922d6..fe9de6ebecc 100644 --- a/src/pages/markets/components/sub-markets/_multipliers.tsx +++ b/src/pages/markets/components/sub-markets/_multipliers.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import AvailablePlatforms from '../helper/_available-platforms' import { ContentWrapper, Descriptions, StyledText } from '../../static/style/_markets-style' import MarketInstruments from '../sections/_market_instruments' @@ -15,6 +15,11 @@ type MultipliersProps = { const Multipliers = ({ market_content }: MultipliersProps) => { const { is_eu } = useRegion() + const [show_eu_content, setShowEuContent] = useState(false) + + useEffect(() => { + if (is_eu) setShowEuContent(true) + }, [is_eu]) return ( @@ -29,7 +34,7 @@ const Multipliers = ({ market_content }: MultipliersProps) => { - {is_eu && + {show_eu_content && market_content.eu_content?.map((text) => ( diff --git a/src/pages/markets/instruments/_crash-boom.tsx b/src/pages/markets/instruments/_crash-boom.tsx index 8e43ed95ca2..fb4e3aa0432 100644 --- a/src/pages/markets/instruments/_crash-boom.tsx +++ b/src/pages/markets/instruments/_crash-boom.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import Symbol from '../components/helper/_symbol' import { crash_boom, @@ -12,9 +12,15 @@ import dclsx from 'features/utils/dclsx' const CrashBoom = () => { const { is_eu } = useRegion() + const [show_eu_content, setShowEuContent] = useState(false) + + useEffect(() => { + if (is_eu) setShowEuContent(true) + }, [is_eu]) + return ( <> - {is_eu ? ( + {show_eu_content ? ( <> {crash_boom_trade_type_eu.map((symbol, index) => ( diff --git a/src/pages/markets/instruments/_european-indices.tsx b/src/pages/markets/instruments/_european-indices.tsx index 449afd77641..57dddf7b0f8 100644 --- a/src/pages/markets/instruments/_european-indices.tsx +++ b/src/pages/markets/instruments/_european-indices.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import Symbol from '../components/helper/_symbol' import { stocks_european_indices } from '../static/content/_market-symbols' import useRegion from 'components/hooks/use-region' @@ -7,23 +7,18 @@ const stocks_european_indices_eu_endpoint = stocks_european_indices.filter((cfds return cfds?.eu === true }) const EuropeanIndices = () => { - const { is_eu, is_row } = useRegion() + const { is_eu } = useRegion() + const [content, setContent] = useState(stocks_european_indices) + + useEffect(() => { + if (is_eu) setContent(stocks_european_indices_eu_endpoint) + }, [is_eu]) + return ( <> - {is_row && ( - <> - {stocks_european_indices.map((symbol, index) => ( - - ))} - - )} - {is_eu && ( - <> - {stocks_european_indices_eu_endpoint.map((symbol, index) => ( - - ))} - - )} + {content.map((symbol, index) => ( + + ))} ) } diff --git a/src/pages/markets/instruments/_volatility-indices.tsx b/src/pages/markets/instruments/_volatility-indices.tsx index 995aa66230b..68f2b06fb37 100644 --- a/src/pages/markets/instruments/_volatility-indices.tsx +++ b/src/pages/markets/instruments/_volatility-indices.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import Symbol from '../components/helper/_symbol' import { volatility_indices, @@ -12,10 +12,15 @@ import dclsx from 'features/utils/dclsx' const VolatilityIndices = () => { const { is_eu } = useRegion() + const [show_eu_content, setShowEuContent] = useState(false) + + useEffect(() => { + if (is_eu) setShowEuContent(true) + }, [is_eu]) return ( <> - {is_eu ? ( + {show_eu_content ? ( <> {volatility_indices_trade_type_eu.map((symbol, index) => ( diff --git a/src/pages/markets/static/content/_cfds.tsx b/src/pages/markets/static/content/_cfds.tsx index 1bd7eedc939..cc1f6728a04 100644 --- a/src/pages/markets/static/content/_cfds.tsx +++ b/src/pages/markets/static/content/_cfds.tsx @@ -52,12 +52,12 @@ export const commodities_cfds: TMarketContent = { { id: 'metals', title: '_t_Metals_t_', - component: , + instruments: , }, { id: 'energy', title: '_t_Energy_t_', - component: , + instruments: , }, ], } @@ -72,22 +72,22 @@ export const forex_cfds: TMarketContent = { { id: 'major-pairs', title: '_t_Major pairs_t_', - component: , + instruments: , }, { id: 'minor-pairs', title: '_t_Minor pairs_t_', - component: , + instruments: , }, { id: 'exotic-pairs', title: '_t_Exotic pairs_t_', - component: , + instruments: , }, { id: 'micro-pairs', title: '_t_Micro pairs_t_', - component: , + instruments: , }, ], } @@ -102,12 +102,12 @@ export const forex_cfds_eu: TMarketContent = { { id: 'major-pairs', title: '_t_Major pairs_t_', - component: , + instruments: , }, { id: 'minor-pairs', title: '_t_Minor pairs_t_', - component: , + instruments: , }, ], } @@ -124,44 +124,44 @@ export const synthetic_cfds: TMarketContent = { { id: 'drift-switch-indices', title: '_t_Drift switching indices_t_', - component: , + instruments: , details: , }, { id: 'dex-indices', title: '_t_DEX indices_t_', - component: , + instruments: , details: , }, { id: 'volatility-indices', title: '_t_Volatility indices_t_', - component: , + instruments: , details: , }, { id: 'crash-boom', title: '_t_Crash/Boom_t_', mobile_title: '_t_Crash/Boom_t_', - component: , + instruments: , details: , }, { id: 'jump-indices', title: '_t_Jump indices_t_', - component: , + instruments: , details: , }, { id: 'step-indices', title: '_t_Step indices_t_', - component: , + instruments: , details: , }, { id: 'range-break-indices', title: '_t_Range break indices_t_', - component: , + instruments: , details: , }, ], @@ -179,14 +179,14 @@ export const synthetic_cfds_eu: TMarketContent = { { id: 'volatility-indices', title: '_t_Volatility indices_t_', - component: , + instruments: , details: , }, { id: 'crash-boom', title: '_t_Crash/Boom_t_', mobile_title: '_t_Crash/Boom_t_', - component: , + instruments: , details: , }, ], @@ -200,7 +200,7 @@ export const stock_cfds: TMarketContent = { title: '_t_American <0>indices_t_', title_components: [
], mobile_title: '_t_American indices_t_', - component: , + instruments: , details: , col: 3, tablet_col: 2, @@ -213,7 +213,7 @@ export const stock_cfds: TMarketContent = { title: '_t_Asian <0>indices_t_', title_components: [
], mobile_title: '_t_Asian indices_t_', - component: , + instruments: , details: , col: 3, tablet_col: 2, @@ -226,7 +226,7 @@ export const stock_cfds: TMarketContent = { title: '_t_European <0>indices_t_', title_components: [
], mobile_title: '_t_European indices_t_', - component: , + instruments: , details: , col: 3, tablet_col: 2, @@ -237,7 +237,7 @@ export const stock_cfds: TMarketContent = { { id: 'stocks', title: '_t_Stocks_t_', - component: , + instruments: , col: 3, tablet_col: 2, mobile_col: 2, @@ -260,7 +260,7 @@ export const crypto_cfds: TMarketContent = { { id: 'crypto-pairs', title: '_t_Crypto pairs_t_', - component: , + instruments: , }, ], } @@ -276,13 +276,13 @@ export const basket_cfds: TMarketContent = { { id: 'commodities-basket', title: '_t_Commodities Basket_t_', - component: , + instruments: , details: , }, { id: 'forex-basket', title: '_t_Forex Basket_t_', - component: , + instruments: , details: , }, ], @@ -299,7 +299,7 @@ export const derived_fx_cfds: TMarketContent = { { id: 'cfds-derived-fx', title: '_t_Derived FX_t_', - component: , + instruments: , details: , }, ], diff --git a/src/pages/markets/static/content/_details.tsx b/src/pages/markets/static/content/_details.tsx index 3ed9c2da77e..b6a132a649a 100644 --- a/src/pages/markets/static/content/_details.tsx +++ b/src/pages/markets/static/content/_details.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { CrashText, DetailsContainer } from '../style/_markets-style' import { Text, Ul, Li } from 'components/elements' import { Localize } from 'components/localization' @@ -374,6 +374,12 @@ export const AsianIndicesDetails = () => ( export const EuropeanIndicesDetails = () => { const { is_row } = useRegion() + const [show_row_content, setShowRowContent] = useState(true) + + useEffect(() => { + if (!is_row) setShowRowContent(false) + }, [is_row]) + return ( @@ -397,7 +403,7 @@ export const EuropeanIndicesDetails = () => { components={[]} /> - {is_row && ( + {show_row_content && ( , + instruments: , }, { id: 'energy', title: '_t_Energy_t_', - component: , + instruments: , }, ], markets_list: { @@ -259,12 +259,12 @@ export const forex_options: Options = { { id: 'major-pairs', title: '_t_Major pairs_t_', - component: , + instruments: , }, { id: 'minor-pairs', title: '_t_Minor pairs_t_', - component: , + instruments: , }, ], }, @@ -283,13 +283,13 @@ export const basket_options: Options = { { id: 'commodities-basket', title: '_t_Commodities Basket_t_', - component: , + instruments: , details: , }, { id: 'forex-basket', title: '_t_Forex Basket_t_', - component: , + instruments: , details: , }, ], @@ -307,7 +307,7 @@ export const stock_options: Options = { title: '_t_American <0>indices_t_', title_components: [
], mobile_title: '_t_American indices_t_', - component: , + instruments: , details: , tablet_col: 2, mobile_col: 2, @@ -320,7 +320,7 @@ export const stock_options: Options = { title: '_t_Asian <0>indices_t_', title_components: [
], mobile_title: '_t_Asian indices_t_', - component: , + instruments: , details: , tablet_col: 2, mobile_col: 2, @@ -333,7 +333,7 @@ export const stock_options: Options = { title: '_t_European <0>indices_t_', title_components: [
], mobile_title: '_t_European indices_t_', - component: , + instruments: , details: , col: 3, tablet_col: 2, @@ -353,19 +353,19 @@ export const synthetic_options: Options = { { id: 'continuous-indices', title: '_t_Continuous indices_t_', - component: , + instruments: , details: , }, { id: 'jump-indices', title: '_t_Jump indices_t_', - component: , + instruments: , details: , }, { id: 'daily-reset-indices', title: '_t_Daily reset indices_t_', - component: , + instruments: , details: , }, ], diff --git a/src/pages/markets/static/content/_multipliers.tsx b/src/pages/markets/static/content/_multipliers.tsx index 29da40771ce..e33dc013fd0 100644 --- a/src/pages/markets/static/content/_multipliers.tsx +++ b/src/pages/markets/static/content/_multipliers.tsx @@ -33,7 +33,7 @@ export const forex_multiplier_eu: TMarketContent = { content: [ { title: '_t_Major pairs_t_', - component: , + instruments: , }, ], } @@ -48,7 +48,7 @@ export const forex_multiplier: TMarketContent = { { id: 'major-pairs', title: '_t_Major pairs_t_', - component: , + instruments: , }, ], } @@ -64,13 +64,13 @@ export const basket_multiplier: TMarketContent = { { id: 'commodities-basket', title: '_t_Commodities Basket_t_', - component: , + instruments: , details: , }, { id: 'forex-basket', title: '_t_Forex Basket_t_', - component: , + instruments: , details: , }, ], @@ -86,26 +86,26 @@ export const synthetic_multiplier: TMarketContent = { { id: 'continuous-indices', title: '_t_Continuous indices_t_', - component: , + instruments: , details: , }, { id: 'crash-boom', title: '_t_Crash/Boom_t_', mobile_title: '_t_Crash/Boom_t_', - component: , + instruments: , details: , }, { id: 'jump-indices', title: '_t_Jump indices_t_', - component: , + instruments: , details: , }, { id: 'step-indices', title: '_t_Step indices_t_', - component: , + instruments: , details: , }, ], @@ -125,14 +125,14 @@ export const synthetic_multiplier_eu: TMarketContent = { { title: '_t_Continuous indices_t_', id: 'continuous-indices', - component: , + instruments: , details: , }, { id: 'crash-boom', title: '_t_Crash/Boom_t_', mobile_title: '_t_Crash/Boom_t_', - component: , + instruments: , details: , }, ], @@ -150,7 +150,7 @@ export const crypto_multiplier: TMarketContent = { { id: 'crypto-pairs', title: '_t_Crypto pairs_t_', - component: , + instruments: , details: , }, ], diff --git a/src/pages/markets/static/content/_types.ts b/src/pages/markets/static/content/_types.ts index 3befffe49d6..afcf941347b 100644 --- a/src/pages/markets/static/content/_types.ts +++ b/src/pages/markets/static/content/_types.ts @@ -21,7 +21,7 @@ export type TMarketSymbol = { type TContent = { title: TString - component: React.ReactElement + instruments: React.ReactNode id?: string title_components?: React.ReactElement[] mobile_title?: TString @@ -31,6 +31,7 @@ type TContent = { mobile_col?: number padding?: string gap?: string + flex?: boolean gap_mobile?: string mobile_template?: true } diff --git a/src/pages/markets/synthetic/index.tsx b/src/pages/markets/synthetic/index.tsx index 51e8e27b7e5..a634ea0a487 100644 --- a/src/pages/markets/synthetic/index.tsx +++ b/src/pages/markets/synthetic/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import SyntheticIndices from '../components/markets/_synthetic-indices' import { DerivedFXHero } from '../components/sections/_hero_derived_fx' import NavTab from '../components/sections/_nav-tab' @@ -10,21 +10,28 @@ import useRegion from 'components/hooks/use-region' import { SEO } from 'components/containers' import { usePlatformQueryParam } from 'components/hooks/use-platform-query-param' import { TGatsbyHead } from 'features/types' +import { TString } from 'types/generics' const Markets = () => { const { is_eu, is_row } = useRegion() const { is_deriv_go } = usePlatformQueryParam() + const [description, setDescription] = useState( + '_t_Trade on asset prices derived from simulated markets. Manage your exposure by selecting the volatility level to suit your risk appetite._t_', + ) - const description_eu = - '_t_Trade on asset prices derived from simulated markets. Manage your exposure by selecting the volatility level to suit your risk appetite._t_' - const description_row = - '_t_Trade on asset prices derived from real-world or simulated markets. Manage your exposure by selecting the volatility level to suit your risk appetite. Choose from our 24/7 synthetics, derived FX, and baskets._t_' + useEffect(() => { + if (is_eu) { + setDescription( + '_t_Trade on asset prices derived from real-world or simulated markets. Manage your exposure by selecting the volatility level to suit your risk appetite. Choose from our 24/7 synthetics, derived FX, and baskets._t_', + ) + } + }, [is_eu]) return ( diff --git a/src/pages/partners/_about-deriv.tsx b/src/pages/partners/_about-deriv.tsx index dc7e8f383ee..2a444ea49fe 100644 --- a/src/pages/partners/_about-deriv.tsx +++ b/src/pages/partners/_about-deriv.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { graphql, useStaticQuery } from 'gatsby' import { Container, Flex, Desktop, Mobile } from 'components/containers' @@ -35,6 +35,13 @@ const ImageWrapper = styled.div` const AboutDeriv = () => { const data = useStaticQuery(query) const { is_eu, is_region_loading } = useRegion() + const [platform_content, setPlatformContent] = useState(data.deriv_platform) + + useEffect(() => { + if (is_eu) setPlatformContent(data.deriv_platform_eu) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [is_eu]) + return ( @@ -46,7 +53,7 @@ const AboutDeriv = () => { {!is_region_loading ? ( diff --git a/src/pages/partners/affiliate-ib/_affiliate-ib-hero.tsx b/src/pages/partners/affiliate-ib/_affiliate-ib-hero.tsx new file mode 100644 index 00000000000..1223816873f --- /dev/null +++ b/src/pages/partners/affiliate-ib/_affiliate-ib-hero.tsx @@ -0,0 +1,37 @@ +import React, { useEffect, useState } from 'react' +import Hero from './_hero' +import { StyledHeader, StyledLinkButton } from './_style' +import { Localize } from 'components/localization' +import { TString } from 'types/generics' +import useAffiliateSignupLink from 'features/hooks/ab-testing/use-partners-signup-link' +import useRegion from 'components/hooks/use-region' + +const AffiliateIbHero = () => { + const { is_eu } = useRegion() + const { affiliate_signup_link } = useAffiliateSignupLink() + const [banner_btn, setBannerBtn] = useState('_t_Sign up as our affiliate and IB_t_') + + useEffect(() => { + if (is_eu) setBannerBtn('_t_Sign up as our affiliate_t_') + }, [is_eu]) + + return ( + + + + + + + + + ) +} + +export default AffiliateIbHero diff --git a/src/pages/partners/affiliate-ib/_deriv-ib-programme.tsx b/src/pages/partners/affiliate-ib/_deriv-ib-programme.tsx index 73e791a4cdc..778247b3cfc 100644 --- a/src/pages/partners/affiliate-ib/_deriv-ib-programme.tsx +++ b/src/pages/partners/affiliate-ib/_deriv-ib-programme.tsx @@ -227,7 +227,7 @@ const DerivIBProgramme = () => { setActiveTab(tabName) } } - const deriv_mt5_name: String = 'Deriv MT5' + const deriv_mt5_name = 'Deriv MT5' return ( diff --git a/src/pages/partners/affiliate-ib/_numbers.tsx b/src/pages/partners/affiliate-ib/_numbers.tsx new file mode 100644 index 00000000000..527a71ef07a --- /dev/null +++ b/src/pages/partners/affiliate-ib/_numbers.tsx @@ -0,0 +1,66 @@ +import React, { useEffect, useState } from 'react' +import { + NumberWrapper, + SectionContainerWrapper, + StyledContainer, + StyledSectionContainer, + SubtitleHeader, + StyledNumberText, +} from './_style' +import { Container } from 'components/containers' +import { Header } from 'components/elements' +import { Localize } from 'components/localization' +import useRegion from 'components/hooks/use-region' +import { TString } from 'types/generics' + +type ItemsType = { + title: string + subtitle: TString +}[] + +const items: ItemsType = [ + { title: '60K+', subtitle: '_t_members_t_' }, + { title: '$47M+', subtitle: '_t_paid out since inception_t_' }, + { title: '190+', subtitle: '_t_countries_t_' }, + { title: '1M+', subtitle: '_t_clients_t_' }, +] + +const Numbers = () => { + const { is_eu } = useRegion() + const [earn_text, setEarnText] = useState( + '_t_Earn up to 45% lifetime commission with an online trading provider that enables anyone to trade on several popular financial markets with the utmost convenience. Deriv Group Ltd — the owner of Deriv.com — has a proven track record of running successful referral programmes with prompt payouts._t_', + ) + + useEffect(() => { + if (is_eu) + setEarnText( + "_t_Earn commissions on your referrals' deposits, relying on our track record of prompt payouts and a successful affiliate programme. Your referred clients will enjoy a seamless experience, advanced trading tools, and a wide range of financial instruments on our platforms._t_", + ) + }, [is_eu]) + + return ( + + + + + + + + {items.map(({ title, subtitle }, index) => ( + +
+ {title} +
+ + + +
+ ))} +
+
+
+
+ ) +} + +export default Numbers diff --git a/src/pages/partners/affiliate-ib/_style.tsx b/src/pages/partners/affiliate-ib/_style.tsx index e52fac7329a..3becb361613 100644 --- a/src/pages/partners/affiliate-ib/_style.tsx +++ b/src/pages/partners/affiliate-ib/_style.tsx @@ -1,10 +1,10 @@ import styled from 'styled-components' import { Card } from './_partner-card' import { TRAP } from './_table' -import { Flex } from 'components/containers' +import { Container, Flex, SectionContainer } from 'components/containers' import device from 'themes/device' -import { Text } from 'components/elements' -import { Button } from 'components/form' +import { Header, Text } from 'components/elements' +import { Button, LinkButton } from 'components/form' import { TAlignSelf } from 'features/types' type PointerProps = { @@ -19,6 +19,10 @@ type FlexProps = { align_self?: TAlignSelf } +type StyledLinkButtonProps = { + id?: string +} + export const FormulaBottomWrapper = styled(Flex)` flex-direction: row; justify-content: flex-end; @@ -309,3 +313,83 @@ export const StyledCalculatedButton = styled(Button)` font-size: 1.4rem; } ` + +export const StyledHeader = styled(Header)` + white-space: pre-line; + width: 100%; + max-width: 70rem; + margin-bottom: 4rem; + @media ${device.tabletS} { + font-size: 40px; + text-align: start; + } +` + +export const StyledLinkButton = styled(LinkButton)` + border-radius: 4px; + @media ${device.tabletS} { + font-size: 14px; + padding: 12px 10px; + white-space: nowrap; + } + @media ${device.mobileL} { + font-size: 12px; + } +` + +export const StyledSectionContainer = styled(SectionContainer)` + @media ${device.tabletL} { + padding-top: 40px; + padding-bottom: 40px; + padding-right: 16px; + padding-left: 16px; + } +` + +export const SubtitleHeader = styled(Header)` + width: 1170px; + @media ${device.laptopL} { + width: 100%; + } + @media ${device.tabletL} { + font-size: 16px; + text-align: justify; + } +` +export const SectionContainerWrapper = styled(SectionContainer)` + padding: 4rem; + @media ${device.tabletL} { + padding: 0; + } +` + +export const StyledContainer = styled(Container)` + width: 100%; + direction: ltr; + @media ${device.tabletL} { + flex-wrap: wrap; + margin: 20px 0; + } +` +export const NumberWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + width: 32.8rem; + @media ${device.tabletL} { + padding: 15px; + width: auto; + } + @media ${device.mobileS} { + padding: 10px; + width: auto; + } +` + +export const StyledNumberText = styled(Text)` + padding-top: 8px; + @media ${device.tabletL} { + padding-top: 0; + margin: 12px 0; + } +` diff --git a/src/pages/partners/affiliate-ib/_why-us.tsx b/src/pages/partners/affiliate-ib/_why-us.tsx index bee7225fad5..b7e2d48785a 100644 --- a/src/pages/partners/affiliate-ib/_why-us.tsx +++ b/src/pages/partners/affiliate-ib/_why-us.tsx @@ -6,6 +6,7 @@ import { Header, Text, QueryImage } from 'components/elements' import { Localize, localize } from 'components/localization' import device from 'themes/device' import { TString } from 'types/generics' +import useRegion from 'components/hooks/use-region' export type WhyUsType = { title: TString @@ -107,8 +108,53 @@ const Content = styled.div` } ` -const WhyUs = ({ items }: WhyUsProps) => { +type contentType = { + [T: string]: TString +} + +const WhyUs = () => { const data = useStaticQuery(query) + const { is_eu } = useRegion() + + const content_data: contentType = is_eu + ? { + payout_title: '_t_Zero charges with prompt monthly payouts_t_', + payout_text: + '_t_Deriv Affiliate Programme is free. Enjoy reliable payouts by getting your affiliate commissions paid to your Deriv account._t_', + } + : { + payout_title: '_t_Zero charges with prompt monthly and daily payouts_t_', + payout_text: + '_t_All Deriv partnership programmes are free. Get your affiliate commissions paid to your method of choice every month and IB commissions paid to your Deriv MT5 account daily._t_', + } + + const why_partner_with_us_items: WhyUsType = [ + { + title: '_t_Multiple income opportunities and generous commissions_t_', + subtitle: + '_t_Start off as an affiliate and get ensuing access to our IB programme. Earn commission for as long as your referred clients keep trading._t_', + image_name: 'multiple_income_opportunities', + image_alt: '_t_DMT5 and Dtrader trading platform at Deriv_t_', + only_row: true, + }, + { + title: content_data.payout_title, + subtitle: content_data.payout_text, + image_name: is_eu ? 'daily_ib_commission_eu' : 'daily_ib_commission', + image_alt: '_t_Check your daily IB commission_t_', + }, + { + title: '_t_Optimise conversions with great user experience and creative support_t_', + subtitle: + '_t_We’ve designed a customer-centric and intuitive trading experience for Deriv that’s optimised to convert visitors into clients. We’ll also provide you with the tools and creative materials you need to drive traffic to Deriv._t_', + image_name: 'marketing_material', + image_alt: '_t_Marketing creative material_t_', + }, + ] + + const why_partner_data = is_eu + ? why_partner_with_us_items.filter((item) => !item.only_row) + : why_partner_with_us_items return ( @@ -116,7 +162,7 @@ const WhyUs = ({ items }: WhyUsProps) => { - {items.map((item, index) => { + {why_partner_data.map((item, index) => { const is_even = index % 2 return ( diff --git a/src/pages/partners/affiliate-ib/index.tsx b/src/pages/partners/affiliate-ib/index.tsx index 31ab56638ef..c40ac67c6f7 100644 --- a/src/pages/partners/affiliate-ib/index.tsx +++ b/src/pages/partners/affiliate-ib/index.tsx @@ -1,19 +1,13 @@ import React from 'react' -import styled from 'styled-components' import Loadable from '@loadable/component' -import Hero from './_hero' -import { WhyUsType } from './_why-us' import { faq_schema } from './_faq-schema' -import { Header, Text } from 'components/elements' -import { LinkButton } from 'components/form' +import AffiliateIbHero from './_affiliate-ib-hero' +import Numbers from './_numbers' import Layout from 'components/layout/layout' -import { Container, SectionContainer, SEO, TMetaAttributes } from 'components/containers' -import { Localize, WithIntl } from 'components/localization' -import device from 'themes/device' -import { TString } from 'types/generics' +import { SEO, TMetaAttributes } from 'components/containers' +import { WithIntl } from 'components/localization' import { TGatsbyHead } from 'features/types' import useRegion from 'components/hooks/use-region' -import useAffiliateSignupLink from 'features/hooks/ab-testing/use-partners-signup-link' const WhyUs = Loadable(() => import('./_why-us')) const WhoCanAplly = Loadable(() => import('./_who-can-apply')) @@ -24,199 +18,19 @@ const MoreReason = Loadable(() => import('./_more-reason')) const Faq = Loadable(() => import('./_faq')) const PartnerCTA = Loadable(() => import('./_partner-cta')) -type ItemsType = { - title: string - subtitle: TString -}[] - -type StyledLinkButtonProps = { - id?: string -} - const meta_attributes: TMetaAttributes = { og_title: '_t_Affiliate and IB programme | Deriv_t_', og_description: '_t_Join Deriv’s affiliate and IB programmes and get a chance to be a partner with a trusted online trading provider._t_', } -const StyledHeader = styled(Header)` - white-space: pre-line; - width: 100%; - max-width: 70rem; - margin-bottom: 4rem; - @media ${device.tabletS} { - font-size: 40px; - text-align: start; - } -` - -const StyledLinkButton = styled(LinkButton)` - border-radius: 4px; - @media ${device.tabletS} { - font-size: 14px; - padding: 12px 10px; - white-space: nowrap; - } - @media ${device.mobileL} { - font-size: 12px; - } -` - -const StyledSectionContainer = styled(SectionContainer)` - @media ${device.tabletL} { - padding-top: 40px; - padding-bottom: 40px; - padding-right: 16px; - padding-left: 16px; - } -` - -const SubtitleHeader = styled(Header)` - width: 1170px; - @media ${device.laptopL} { - width: 100%; - } - @media ${device.tabletL} { - font-size: 16px; - text-align: justify; - } -` -const SectionContainerWrapper = styled(SectionContainer)` - padding: 4rem; - @media ${device.tabletL} { - padding: 0; - } -` - -const StyledContainer = styled(Container)` - width: 100%; - direction: ltr; - @media ${device.tabletL} { - flex-wrap: wrap; - margin: 20px 0; - } -` -const NumberWrapper = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - width: 32.8rem; - @media ${device.tabletL} { - padding: 15px; - width: auto; - } - @media ${device.mobileS} { - padding: 10px; - width: auto; - } -` - -const StyledText = styled(Text)` - padding-top: 8px; - @media ${device.tabletL} { - padding-top: 0; - margin: 12px 0; - } -` - -const items: ItemsType = [ - { title: '60K+', subtitle: '_t_members_t_' }, - { title: '$47M+', subtitle: '_t_paid out since inception_t_' }, - { title: '190+', subtitle: '_t_countries_t_' }, - { title: '1M+', subtitle: '_t_clients_t_' }, -] - -type contentType = { - [T: string]: TString -} const AffiliateIb = () => { const { is_eu } = useRegion() - const { affiliate_signup_link } = useAffiliateSignupLink() - - const content_data: contentType = is_eu - ? { - banner_btn: '_t_Sign up as our affiliate_t_', - earn_text: - "_t_Earn commissions on your referrals' deposits, relying on our track record of prompt payouts and a successful affiliate programme. Your referred clients will enjoy a seamless experience, advanced trading tools, and a wide range of financial instruments on our platforms._t_", - payout_title: '_t_Zero charges with prompt monthly payouts_t_', - payout_text: - '_t_Deriv Affiliate Programme is free. Enjoy reliable payouts by getting your affiliate commissions paid to your Deriv account._t_', - } - : { - banner_btn: '_t_Sign up as our affiliate and IB_t_', - earn_text: - '_t_Earn up to 45% lifetime commission with an online trading provider that enables anyone to trade on several popular financial markets with the utmost convenience. Deriv Group Ltd — the owner of Deriv.com — has a proven track record of running successful referral programmes with prompt payouts._t_', - payout_title: '_t_Zero charges with prompt monthly and daily payouts_t_', - payout_text: - '_t_All Deriv partnership programmes are free. Get your affiliate commissions paid to your method of choice every month and IB commissions paid to your Deriv MT5 account daily._t_', - } - - const why_partner_with_us_items: WhyUsType = [ - { - title: '_t_Multiple income opportunities and generous commissions_t_', - subtitle: - '_t_Start off as an affiliate and get ensuing access to our IB programme. Earn commission for as long as your referred clients keep trading._t_', - image_name: 'multiple_income_opportunities', - image_alt: '_t_DMT5 and Dtrader trading platform at Deriv_t_', - only_row: true, - }, - { - title: content_data.payout_title, - subtitle: content_data.payout_text, - image_name: is_eu ? 'daily_ib_commission_eu' : 'daily_ib_commission', - image_alt: '_t_Check your daily IB commission_t_', - }, - { - title: '_t_Optimise conversions with great user experience and creative support_t_', - subtitle: - '_t_We’ve designed a customer-centric and intuitive trading experience for Deriv that’s optimised to convert visitors into clients. We’ll also provide you with the tools and creative materials you need to drive traffic to Deriv._t_', - image_name: 'marketing_material', - image_alt: '_t_Marketing creative material_t_', - }, - ] - - const why_partner_data = is_eu - ? why_partner_with_us_items.filter((item) => !item.only_row) - : why_partner_with_us_items return ( - - - - - - - - - - - - - - - - {items.map(({ title, subtitle }, index) => ( - -
- {title} -
- - - -
- ))} -
-
-
-
+ + {!is_eu && ( <> @@ -224,7 +38,7 @@ const AffiliateIb = () => { )} - + diff --git a/src/pages/payment-methods/index.tsx b/src/pages/payment-methods/index.tsx index 58b82ff10be..da19575d366 100644 --- a/src/pages/payment-methods/index.tsx +++ b/src/pages/payment-methods/index.tsx @@ -12,7 +12,6 @@ import { WithIntl, Localize } from 'components/localization' import device from 'themes/device' import useRegion from 'components/hooks/use-region' import useWS from 'components/hooks/useWS' -import { isBrowser } from 'common/utility' import Flex from 'features/components/atoms/flex-box' import Typography from 'features/components/atoms/typography' import { TGatsbyHead } from 'features/types' @@ -110,7 +109,7 @@ export type PaymentMethodsProps = { pd?: PaymentDataProps } const DisplayAccordion = ({ locale }: PaymentMethodsProps) => { - const { is_p2p_allowed_country, is_eu } = useRegion() + const { is_p2p_allowed_country, is_eu, is_region_loading } = useRegion() const [is_mobile] = useBrowserResize(992) const { data, send } = useWS('crypto_config') const [payment_method_data, setPaymentMethodData] = useState(payment_data) @@ -169,7 +168,7 @@ const DisplayAccordion = ({ locale }: PaymentMethodsProps) => { } const parent_style = { marginBottom: is_mobile ? '24px' : '2.4rem' } - if (!isBrowser()) { + if (is_region_loading) { return } return ( diff --git a/src/pages/regulatory/_info-row-cpa.tsx b/src/pages/regulatory/_info-row-cpa.tsx new file mode 100644 index 00000000000..d6edd534388 --- /dev/null +++ b/src/pages/regulatory/_info-row-cpa.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import { + DesktopWrapper, + MobileWrapper, + ResponsiveGrid, + StyledHeader, + StyledLinkText, +} from './_style' +import { Localize } from 'components/localization' +import { CssGridColumn } from 'components/containers' +import { Text } from 'components/elements' + +const InfoRowCpa = () => { + return ( + <> + + + + + + + + + + + + + + + , + ]} + /> + + + + ) +} + +export default InfoRowCpa diff --git a/src/pages/regulatory/_investment-europe.tsx b/src/pages/regulatory/_investment-europe.tsx new file mode 100644 index 00000000000..b6a700b8ad9 --- /dev/null +++ b/src/pages/regulatory/_investment-europe.tsx @@ -0,0 +1,88 @@ +import React from 'react' +import EUgrid from './_eu-grid' +import DocumentAccordion from './_document_accordion' +import { Box, Europe, StyledHeader, StyledLinkText } from './_style' +import { RegulatoryProps } from './_type' +import { Header } from 'components/elements' +import { + CssGrid, + CssGridColumn, + GridContainer, + SectionContainer, + SmallContainer, +} from 'components/containers' +import { Localize } from 'components/localization' +// Icons +import EU from 'images/svg/regulatory/europe-map.svg' + +const InvestmentEurope = ({ locale }: { locale: RegulatoryProps }) => { + return ( + <> + + + + + + +
+ , + ]} + /> +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default InvestmentEurope diff --git a/src/pages/regulatory/_style.tsx b/src/pages/regulatory/_style.tsx new file mode 100644 index 00000000000..9916500eaaf --- /dev/null +++ b/src/pages/regulatory/_style.tsx @@ -0,0 +1,76 @@ +import styled from 'styled-components' +import { BoxProps } from './_type' +import device from 'themes/device' +import { Header, LinkText, Text } from 'components/elements' +import { CssGridColumn, Desktop, Mobile } from 'components/containers' + +export const Img = styled.img` + display: flex; + width: 16rem; + height: 8rem; +` + +export const ImgFintech = styled.img` + display: flex; + width: 160px; + height: 38.8px; +` + +export const StyledHeader = styled(Header)<{ maxwidth?: string }>` + max-width: ${(props) => props.maxwidth || '100%'}; + margin: 0 auto; + @media ${device.tabletS} { + text-align: center; + margin-bottom: 1.6rem; + } +` + +export const MobileWrapper = styled(Mobile)` + display: flex; +` + +export const DesktopWrapper = styled(Desktop)` + display: flex; +` +export const Box = styled.div` + display: flex; + flex-direction: column; + align-items: center; + padding: ${(props) => props.padding || '4rem 0 0'}; + max-width: ${(props) => props.maxwidth || '100%'}; + ${Text} { + @media ${device.tabletS} { + text-align: center; + } + } + @media ${device.tabletS} { + text-align: center; + } +` +export const Europe = styled.img` + max-width: 69rem; + max-height: 63rem; + width: 100%; + height: 100%; + margin: 0; +` + +export const ResponsiveGrid = styled(CssGridColumn)` + @media ${device.tabletL} { + justify-self: center; + justify-content: center; + display: flex; + flex-direction: column; + align-items: center; + } +` + +export const ResponsiveHeader = styled(StyledHeader)` + @media ${device.mobileL} { + font-size: 5rem; + } +` + +export const StyledLinkText = styled(LinkText)` + font-weight: bold; +` diff --git a/src/pages/regulatory/_type.ts b/src/pages/regulatory/_type.ts new file mode 100644 index 00000000000..2fb8bc88144 --- /dev/null +++ b/src/pages/regulatory/_type.ts @@ -0,0 +1,8 @@ +export type BoxProps = { + padding?: string + maxwidth?: string +} + +export type RegulatoryProps = { + language: string +} diff --git a/src/pages/regulatory/index.tsx b/src/pages/regulatory/index.tsx index 6a5b1f91c66..00dad91a9ea 100644 --- a/src/pages/regulatory/index.tsx +++ b/src/pages/regulatory/index.tsx @@ -1,24 +1,30 @@ -import React from 'react' -import styled from 'styled-components' -import EUgrid from './_eu-grid' -import DocumentAccordion from './_document_accordion' +import React, { useEffect, useState } from 'react' import FinancialCommission from './_financial_commission' -import useRegion from 'components/hooks/use-region' +import { RegulatoryProps } from './_type' +import { + DesktopWrapper, + Img, + ImgFintech, + MobileWrapper, + ResponsiveGrid, + ResponsiveHeader, + StyledHeader, + StyledLinkText, +} from './_style' +import InfoRowCpa from './_info-row-cpa' +import InvestmentEurope from './_investment-europe' import Layout from 'components/layout/layout' -import { Divider, Header, LinkText, Text } from 'components/elements' +import { Divider, Text } from 'components/elements' import { CssGrid, CssGridColumn, - Desktop, GridContainer, - Mobile, SectionContainer, SEO, SmallContainer, } from 'components/containers' import { Localize, WithIntl } from 'components/localization' // Icons -import EU from 'images/svg/regulatory/europe-map.svg' import Vanuatu from 'images/common/regulatory/vanuatu.svg' import VanuatuFMA from 'images/common/regulatory/vanuatu-fma.svg' import FSC from 'images/common/regulatory/bvi.svg' @@ -26,94 +32,24 @@ import LabuanFintech from 'images/common/regulatory/labuan-fintech.svg' import Deriv from 'images/common/regulatory/deriv.svg' import TFC from 'images/common/regulatory/tfc.svg' import SVG from 'images/svg/regulatory/svg.svg' -import device from 'themes/device' import useBreakpoints from 'components/hooks/use-breakpoints' import { TGatsbyHead } from 'features/types' +import useRegion from 'components/hooks/use-region' import InitialLoader from 'components/elements/dot-loader' -type BoxProps = { - padding?: string - maxwidth?: string -} - -type RegulatoryProps = { - language: string -} - -const Img = styled.img` - display: flex; - width: 16rem; - height: 8rem; -` - -const ImgFintech = styled.img` - display: flex; - width: 160px; - height: 38.8px; -` - -const StyledHeader = styled(Header)<{ maxwidth?: string }>` - max-width: ${(props) => props.maxwidth || '100%'}; - margin: 0 auto; - @media ${device.tabletS} { - text-align: center; - margin-bottom: 1.6rem; - } -` - -const MobileWrapper = styled(Mobile)` - display: flex; -` - -const DesktopWrapper = styled(Desktop)` - display: flex; -` -const Box = styled.div` - display: flex; - flex-direction: column; - align-items: center; - padding: ${(props) => props.padding || '4rem 0 0'}; - max-width: ${(props) => props.maxwidth || '100%'}; - ${Text} { - @media ${device.tabletS} { - text-align: center; - } - } - @media ${device.tabletS} { - text-align: center; - } -` -const Europe = styled.img` - max-width: 69rem; - max-height: 63rem; - width: 100%; - height: 100%; - margin: 0; -` - -const ResponsiveGrid = styled(CssGridColumn)` - @media ${device.tabletL} { - justify-self: center; - justify-content: center; - display: flex; - flex-direction: column; - align-items: center; - } -` - -const ResponsiveHeader = styled(StyledHeader)` - @media ${device.mobileL} { - font-size: 5rem; - } -` - -const StyledLinkText = styled(LinkText)` - font-weight: bold; -` - const Regulatory = (locale: RegulatoryProps) => { - const { is_row, is_cpa_plan, is_region_loading } = useRegion() const { is_mobile } = useBreakpoints() + const { is_row, is_cpa_plan, is_region_loading } = useRegion() + const [is_row_cpa, setIsRowCpa] = useState(true) + const investment_euroupe = is_row_cpa ? : null + + useEffect(() => { + if (is_row || is_cpa_plan) { + setIsRowCpa(false) + } else { + setIsRowCpa(true) + } + }, [is_row, is_cpa_plan]) return ( @@ -143,94 +79,8 @@ const Regulatory = (locale: RegulatoryProps) => {
- {!is_region_loading ? ( - is_row || is_cpa_plan ? null : ( - <> - - - - - - -
- , - ]} - /> -
-
- -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - ) - ) : ( - - )} + + {is_region_loading ? : investment_euroupe} @@ -242,37 +92,7 @@ const Regulatory = (locale: RegulatoryProps) => { tablet_columns="1fr 5fr" mobile_columns="1fr" > - {is_row || is_cpa_plan ? ( - <> - - - - - - - - - - - - - - - , - ]} - /> - - - - ) : null} + {!is_row_cpa && } diff --git a/src/pages/responsible/index.tsx b/src/pages/responsible/index.tsx index faf7e453f37..7326f9f6a77 100644 --- a/src/pages/responsible/index.tsx +++ b/src/pages/responsible/index.tsx @@ -9,8 +9,8 @@ import { Localize, WithIntl } from 'components/localization' import NoneEuBackground from 'images/common/responsible-trading-bg.png' import EuBackground from 'images/common/responsible-trading-eu-bg.png' import device from 'themes/device' -import useRegion from 'components/hooks/use-region' import { TGatsbyHead } from 'features/types' +import { useShowEuContent } from 'components/hooks/use-show-eu-content' const TradingResponsibly = Loadable(() => import('./_trading-responsibly')) const TradingLimits = Loadable(() => import('./_trading-limits')) @@ -34,13 +34,12 @@ const StyledHeader = styled(Header)` ` const ResponsibleTrading = () => { - const { is_eu, is_non_eu } = useRegion() - const HeroBackground = is_eu ? EuBackground : NoneEuBackground + const show_eu_content = useShowEuContent() return (
- + { - {is_eu && ( + {show_eu_content && ( )} - {is_non_eu && ( + {!show_eu_content && ( )} diff --git a/src/pages/signup-affiliates/_types.ts b/src/pages/signup-affiliates/_types.ts index 5006e1f2f45..21c1af42a78 100644 --- a/src/pages/signup-affiliates/_types.ts +++ b/src/pages/signup-affiliates/_types.ts @@ -1,14 +1,14 @@ import { Dispatch, ReactElement, SetStateAction } from 'react' -type CountryType = { name?: string; display_name?: string; prefix?: string; symbol?: string } +type ResidenceType = { name?: string; display_name?: string; prefix?: string; symbol?: string } type AffiliateAccountTypes = { email: string account_type: number account_plan: number account_address: { - country: CountryType - state: { name?: string; display_name?: string } + country: ResidenceType + state: ResidenceType city: string street: string postal_code: string @@ -70,6 +70,7 @@ type AffiliateAccountProps = { export type SignUpStatusTypes = | 'Username not available' | 'lost connection' + | 'unhandled error' | 'success' | 'loading' | 'Your website is not a valid entry' @@ -118,7 +119,7 @@ type WizardStepProps = { affiliate_account: AffiliateAccountTypes updateData: (value: AffiliateAccountTypes[T]) => void onValidate: (value: boolean) => void - residence_list?: CountryType[] + residence_list?: ResidenceType[] is_individual?: boolean } diff --git a/src/pages/signup-affiliates/components/_account-address.tsx b/src/pages/signup-affiliates/components/_account-address.tsx index b739ad061a8..e1006d63c5f 100644 --- a/src/pages/signup-affiliates/components/_account-address.tsx +++ b/src/pages/signup-affiliates/components/_account-address.tsx @@ -17,11 +17,14 @@ const AccountAddress = ({ }: WizardStepProps<'account_address'>) => { const [form_data, setFormData] = useState(affiliate_account.account_address) const [form_errors, setFormErrors] = useState({ - country_error_msg: '', + country_error_msg: affiliate_validation['country'](form_data['country']) ?? '', state_error_msg: '', - city_error_msg: '', - street_error_msg: '', - postal_code_error_msg: '', + city_error_msg: form_data.city && (affiliate_validation['city'](form_data['city']) ?? ''), + street_error_msg: + form_data.street && (affiliate_validation['street'](form_data['street']) ?? ''), + postal_code_error_msg: + form_data.postal_code && + (affiliate_validation['postal_code'](form_data['postal_code']) ?? ''), }) const [states_list] = useStatesList(form_data.country?.symbol) const header_text: TString = is_individual ? '_t_Personal address_t_' : '_t_Company address_t_' @@ -103,7 +106,7 @@ const AccountAddress = ({ !form_errors.street_error_msg && !form_errors.postal_code_error_msg, ) - }, [form_data]) + }, [form_data, form_errors]) const handleInput = useCallback((e: React.ChangeEvent) => { const { name, value } = e.target @@ -157,6 +160,7 @@ const AccountAddress = ({ label={item.label} placeholder={item.label} onChange={handleInput} + onBlur={handleInput} handleError={() => handleError(item)} /> diff --git a/src/pages/signup-affiliates/components/_account-details.tsx b/src/pages/signup-affiliates/components/_account-details.tsx index 1e8d8b59ee3..fac85fcd4f4 100644 --- a/src/pages/signup-affiliates/components/_account-details.tsx +++ b/src/pages/signup-affiliates/components/_account-details.tsx @@ -7,25 +7,7 @@ import AffiliatesHeader, { InputGroup, InputWrapper } from '../utils/_affiliate- import Typography from 'features/components/atoms/typography' import { Localize, localize } from 'components/localization' -const AccountDetails = ({ - is_individual, - affiliate_account, - updateData, - onValidate, -}: WizardStepProps<'account_details'>) => { - const [form_data, setFormData] = useState(affiliate_account.account_details) - const [form_errors, setFormErrors] = useState({ - user_name_error_msg: '', - first_name_error_msg: '', - last_name_error_msg: '', - phone_error_msg: '', - company_name_error_msg: '', - company_registration_number_error_msg: '', - website_url_error_msg: '', - second_website_url_error_msg: '', - password_error_msg: '', - }) - +const getFormFields = (is_individual: boolean) => { const company_fields = !is_individual ? [ { @@ -43,7 +25,7 @@ const AccountDetails = ({ ] : [] - const form_inputs = [ + return [ { id: 'dm-first_name', name: 'first_name', @@ -98,6 +80,44 @@ const AccountDetails = ({ label: localize('_t_Password*_t_'), }, ] +} + +const AccountDetails = ({ + is_individual, + affiliate_account, + updateData, + onValidate, +}: WizardStepProps<'account_details'>) => { + const [form_data, setFormData] = useState(affiliate_account.account_details) + const [form_errors, setFormErrors] = useState({ + username_error_msg: + form_data.username && (affiliate_validation['username'](form_data['username']) ?? ''), + first_name_error_msg: + form_data.first_name && + (affiliate_validation['first_name'](form_data['first_name']) ?? ''), + last_name_error_msg: + form_data.last_name && + (affiliate_validation['last_name'](form_data['last_name']) ?? ''), + phone_error_msg: Number.isInteger(Number(form_data.phone?.substring(1))) + ? '' + : affiliate_validation['phone'](form_data['phone']), + company_name_error_msg: + form_data.company_name && + (affiliate_validation['company_name'](form_data['company_name']) ?? ''), + company_registration_number_error_msg: + form_data.company_registration_number && + (affiliate_validation['company_registration_number']( + form_data['company_registration_number'], + ) ?? + ''), + website_url_error_msg: + form_data.website_url && + (affiliate_validation['website_url'](form_data['website_url']) ?? ''), + second_website_url_error_msg: '', + password_error_msg: + form_data.password && (affiliate_validation['password'](form_data['password']) ?? ''), + }) + const form_inputs = getFormFields(is_individual) useEffect(() => { updateData({ ...form_data }) @@ -132,15 +152,13 @@ const AccountDetails = ({ !form_errors.company_name_error_msg && !form_errors.company_registration_number_error_msg, ) - }, [form_data]) + }, [form_data, form_errors]) const handleInput = useCallback((e: React.ChangeEvent) => { const { name, value } = e.target - setFormData((prev) => ({ ...prev, [name]: value })) - if (affiliate_validation[name]) { - const error_msg = affiliate_validation[name](value) + const error_msg = affiliate_validation[name](value) || '' setFormErrors((errors) => ({ ...errors, [`${name}_error_msg`]: error_msg, @@ -205,6 +223,7 @@ const AccountDetails = ({ placeholder={item.label} password_icon={item.type == 'password'} onChange={handleInput} + onBlur={handleInput} data-lpignore="true" handleError={() => handleError(item)} /> diff --git a/src/pages/signup-affiliates/components/_account-plan.tsx b/src/pages/signup-affiliates/components/_account-plan.tsx index fa8ee8a1c73..0d682ded58a 100644 --- a/src/pages/signup-affiliates/components/_account-plan.tsx +++ b/src/pages/signup-affiliates/components/_account-plan.tsx @@ -4,40 +4,49 @@ import { StyledHeader } from '../utils/_affiliate-header' import AccountCard, { AccountCardProps, MainWrapper } from '../utils/_account-card' import { Localize } from 'components/localization' import { useIsRtl } from 'components/hooks/use-isrtl' +import useRegion from 'components/hooks/use-region' import Revenue from 'images/svg/signup-affiliates/revenue.svg' import Turnover from 'images/svg/signup-affiliates/turnover.svg' import CPA from 'images/svg/signup-affiliates/cpa.svg' -const plans: AccountCardProps[] = [ - { - value: 2, - icon: Revenue, - title: '_t_Revenue share_t_', - description: - '_t_Earn based on the monthly net revenue generated by your client. <0>Learn more_t_', - }, - { - value: 4, - icon: Turnover, - title: '_t_Turnover_t_', - description: - "_t_Earn based on each contract's payout probability or client's trade. <0>Learn more_t_", - }, - { - value: 6, - icon: CPA, - title: '_t_CPA (EU only)_t_', - description: '_t_Earn based on each successful referral. <0>Learn more_t_', - note: '_t_<0>Note: This plan is available exclusively for EU-based clients only._t_', - }, -] +const getPlans = (is_eu: boolean, is_cpa_plan: boolean): AccountCardProps[] => { + const plans: AccountCardProps[] = [ + { + value: 2, + icon: Revenue, + title: '_t_Revenue share_t_', + description: + '_t_Earn based on the monthly net revenue generated by your client. <0>Learn more_t_', + }, + { + value: 4, + icon: Turnover, + title: '_t_Turnover_t_', + description: + "_t_Earn based on each contract's payout probability or client's trade. <0>Learn more_t_", + }, + ] + if (is_eu || is_cpa_plan) { + plans.push({ + value: 6, + icon: CPA, + title: '_t_CPA (EU only)_t_', + description: '_t_Earn based on each successful referral. <0>Learn more_t_', + note: '_t_<0>Note: This plan is available exclusively for EU-based clients only._t_', + }) + } + return plans +} + const AccountPlan = ({ affiliate_account, updateData, onValidate, }: WizardStepProps<'account_plan'>) => { const [account_plan, setAccountPlan] = useState(affiliate_account.account_plan) + const { is_eu, is_cpa_plan } = useRegion() const is_rtl = useIsRtl() + const plans = getPlans(is_eu, is_cpa_plan) useEffect(() => { updateData(account_plan) diff --git a/src/pages/signup-affiliates/components/_signup-status.tsx b/src/pages/signup-affiliates/components/_signup-status.tsx index 9f193ad23fb..833ddfc7953 100644 --- a/src/pages/signup-affiliates/components/_signup-status.tsx +++ b/src/pages/signup-affiliates/components/_signup-status.tsx @@ -98,8 +98,8 @@ const CloseButton = styled.img` } ` -const user_name = localize('_t_User name_t_') -const web_site = localize('_t_Website url_t_') +const user_name = localize('_t_Username*_t_') +const web_site = localize('_t_Website/social media URL*_t_') const AffiliateSignupStatus = ({ signup_status, @@ -108,8 +108,8 @@ const AffiliateSignupStatus = ({ setAffiliateAccount, onSubmit, }: SignUpStatusProps) => { - const [username_error, setUsernameError] = useState() - const [website_url_error, setWebsiteUrlError] = useState() + const [username_error, setUsernameError] = useState(' ') + const [website_url_error, setWebsiteUrlError] = useState(' ') const is_rtl = useIsRtl() const handleStateChange = useCallback( @@ -142,7 +142,7 @@ const AffiliateSignupStatus = ({ const handleTryAgain = useCallback(() => { setSignupStatus('loading') onSubmit() - }, [signup_status]) + }, [signup_status, onSubmit]) return ( <> @@ -230,6 +230,23 @@ const AffiliateSignupStatus = ({ )} + {signup_status == 'unhandled error' && ( + + + email +
+ +
+
+ +
+ + + +
+ +
+ )} {signup_status == 'Username not available' && ( @@ -256,7 +273,11 @@ const AffiliateSignupStatus = ({ handleError={() => handleStateChange({ field: 'username' })} required /> - + @@ -283,7 +304,11 @@ const AffiliateSignupStatus = ({ handleError={() => handleStateChange({ field: 'website_url' })} required /> - + diff --git a/src/pages/signup-affiliates/components/_wizard.tsx b/src/pages/signup-affiliates/components/_wizard.tsx index 0b5f7cbdb63..912b627c9cf 100644 --- a/src/pages/signup-affiliates/components/_wizard.tsx +++ b/src/pages/signup-affiliates/components/_wizard.tsx @@ -64,13 +64,6 @@ const Wizard = ({ }} onValidate={setNextBtnEnabled} /> - { - updateAffiliateValues<'account_plan'>(value, 'account_plan') - }} - onValidate={setNextBtnEnabled} - /> + { + updateAffiliateValues<'account_plan'>(value, 'account_plan') + }} + onValidate={setNextBtnEnabled} + /> { diff --git a/src/pages/signup-affiliates/components/wizard-component/stepper.tsx b/src/pages/signup-affiliates/components/wizard-component/stepper.tsx index 32c80d8aafb..7610eaa90f4 100644 --- a/src/pages/signup-affiliates/components/wizard-component/stepper.tsx +++ b/src/pages/signup-affiliates/components/wizard-component/stepper.tsx @@ -105,22 +105,22 @@ const steps: { id: number; step_num: TString; step_name: TString; step_descripti }, { id: 2, - step_num: '_t_Step 2 : Subscription plan (2 of 5)_t_', - step_name: '_t_Subscription plan_t_', - step_description: '_t_Choose which plan you would like to subscribe._t_', - }, - { - id: 3, - step_num: '_t_Step 3 : Address details (3 of 5)_t_', + step_num: '_t_Step 2 : Address details (2 of 5)_t_', step_name: '_t_Address details_t_', step_description: '_t_Personal address_t_', }, { - id: 4, - step_num: '_t_Step 4 : Personal details (4 of 5)_t_', + id: 3, + step_num: '_t_Step 3 : Personal details (3 of 5)_t_', step_name: '_t_Personal details_t_', step_description: '_t_ Details_t_', }, + { + id: 4, + step_num: '_t_Step 4 : Subscription plan (4 of 5)_t_', + step_name: '_t_Subscription plan_t_', + step_description: '_t_Choose which plan you would like to subscribe._t_', + }, { id: 5, step_num: '_t_Step 5 : Terms of use (5 of 5)_t_', diff --git a/src/pages/signup-affiliates/index.tsx b/src/pages/signup-affiliates/index.tsx index 25dbd6f2700..8fb84f60e2b 100644 --- a/src/pages/signup-affiliates/index.tsx +++ b/src/pages/signup-affiliates/index.tsx @@ -19,11 +19,12 @@ const meta_attributes: TMetaAttributes = { '_t_Partner with us as an affiliate. Earn commission from the total net revenue of your referred clients’ trades on Deriv Trader, Deriv Bot, and SmartTrader._t_', } -const ParentWrapper = styled.div` +const ParentWrapper = styled.div<{ isPopupOpen?: boolean }>` block-size: calc(100svh - 70px); background-image: url(${Map}); background-repeat: no-repeat; background-position: bottom; + overflow: ${({ isPopupOpen }) => (isPopupOpen ? 'hidden' : 'auto')}; @media ${device.tabletL} { background-image: unset; @@ -87,17 +88,6 @@ const AffiliateSignup = () => { send: affiliateSend, } = useWS('affiliate_register_person') - useEffect(() => { - trackEvent({ action: 'open' }) - const handleBeforeUnload = (event) => { - event.preventDefault() - trackEvent({ action: 'close' }) - trackEvent({ action: 'close_wizard' }) - } - window.addEventListener('beforeunload', handleBeforeUnload) - return () => window.removeEventListener('beforeunload', handleBeforeUnload) - }, []) - useEffect(() => { const handleStatusChange = () => { if (!navigator.onLine) trackEvent({ action: 'other_error' }) @@ -128,12 +118,14 @@ const AffiliateSignup = () => { } else if ( partner_signup_error_message == 'Your website is not a valid entry' || partner_signup_error_message == "String does not match '^[0-9A-Za-z.-]{5,250}$'" || - partner_signup_error_message == 'Input validation failed: website_url' + partner_signup_error_message?.includes('website_url') ) { trackEvent({ action: 'partners_signup_error', partner_signup_error_message }) setSignupStatus('Your website is not a valid entry') - } else if (partner_signup_error_message) + } else if (partner_signup_error_message) { trackEvent({ action: 'other_error', partner_signup_error_message }) + setSignupStatus('unhandled error') + } }, [affiliate_api_data, affiliate_api_error]) useEffect(() => { @@ -154,7 +146,7 @@ const AffiliateSignup = () => { return ( - + {show_wizard ? ( diff --git a/src/pages/signup-affiliates/utils/_affiliate-input.tsx b/src/pages/signup-affiliates/utils/_affiliate-input.tsx index 87d9b41c8d0..8121c99ca21 100644 --- a/src/pages/signup-affiliates/utils/_affiliate-input.tsx +++ b/src/pages/signup-affiliates/utils/_affiliate-input.tsx @@ -110,6 +110,7 @@ const AffiliateInput = ({ background="white" ref={() => current_input} type={is_password_visible ? 'text' : props.type} + autoComplete="off" /> {label && ( diff --git a/src/pages/signup-affiliates/utils/_utils.tsx b/src/pages/signup-affiliates/utils/_utils.tsx index 3a18e197175..787b1f96cd7 100644 --- a/src/pages/signup-affiliates/utils/_utils.tsx +++ b/src/pages/signup-affiliates/utils/_utils.tsx @@ -1,24 +1,6 @@ import { Analytics, TEvents } from '@deriv-com/analytics' import { SubmitTypes } from '../_types' -export const customSlugify = (text: string): string => { - const charMap: { [key: string]: string } = { - ə: 'e', - '(': ' ', - ')': ' ', - // Add other special characters and their mappings here if needed - } - return text - .toString() - .split('') - .map((char) => charMap[char] || char) - .join('') - .normalize('NFD') - .replace(/[\u0300-\u036f]/g, '') - .trim() - .replace(/'/g, '') - .replace(/--+/g, '-') -} export const Submit = ({ is_online, affiliate_account, @@ -34,24 +16,28 @@ export const Submit = ({ }) } else affiliateSend({ - email: affiliate_account.email, + email: affiliate_account.email.trim(), type_of_account: affiliate_account.account_type, commission_plan: affiliate_account.account_plan, country: affiliate_account.account_address.country.symbol, - address_city: affiliate_account.account_address.city, - address_postcode: affiliate_account.account_address.postal_code, - address_state: customSlugify(affiliate_account.account_address.state.name), - address_street: affiliate_account.account_address.street, - first_name: affiliate_account.account_details.first_name, - last_name: affiliate_account.account_details.last_name, + address_city: affiliate_account.account_address.city.trim(), + address_postcode: affiliate_account.account_address.postal_code.trim(), + address_state: affiliate_account.account_address.state.symbol, + address_street: affiliate_account.account_address.street.trim(), + first_name: affiliate_account.account_details.first_name.trim(), + last_name: affiliate_account.account_details.last_name.trim(), date_of_birth: affiliate_account.account_details.date_birth?.toISOString().slice(0, 10), over_18_declaration: 1, - website_url: affiliate_account.account_details?.website_url.includes('www.') - ? affiliate_account.account_details?.website_url - : `www.${affiliate_account.account_details?.website_url}`, - user_name: affiliate_account.account_details.username, + website_url: + affiliate_account.account_details?.website_url.includes('https://') || + affiliate_account.account_details?.website_url.includes('http://') + ? affiliate_account.account_details?.website_url.trim() + : `https://${affiliate_account.account_details?.website_url.trim()}`, + user_name: affiliate_account.account_details.username.trim(), password: affiliate_account.account_details.password, - phone: affiliate_account.account_details.phone, + phone: affiliate_account.account_details.phone.includes('+') + ? affiliate_account.account_details.phone + : `+${affiliate_account.account_details.phone}`, phone_code: Number(affiliate_account.account_details.phone.substring(1, 4)), whatsapp_number: affiliate_account.account_details.phone, whatsapp_number_phoneCode: Number( @@ -61,11 +47,11 @@ export const Submit = ({ tnc_accepted: affiliate_account.terms_of_use.tnc_accepted && 1, tnc_affiliate_accepted: affiliate_account.terms_of_use.tnc_affiliate_accepted && 1, ...(affiliate_account.account_details?.company_name !== '' && { - company_name: affiliate_account.account_details?.company_name, + company_name: affiliate_account.account_details?.company_name.trim(), }), ...(affiliate_account.account_details?.company_registration_number !== '' && { company_registration_number: - affiliate_account.account_details?.company_registration_number, + affiliate_account.account_details?.company_registration_number.trim(), }), }) } diff --git a/src/pages/signup-affiliates/validations/_affilaite_validation.tsx b/src/pages/signup-affiliates/validations/_affilaite_validation.tsx index 37d9f2ff4d4..e58038c41c1 100644 --- a/src/pages/signup-affiliates/validations/_affilaite_validation.tsx +++ b/src/pages/signup-affiliates/validations/_affilaite_validation.tsx @@ -2,212 +2,178 @@ import { localize } from 'components/localization' /* eslint-disable */ export const affiliate_validation_regex = { - email: /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/, - latin: /[^a-zA-Za 0-9-]/, - name: /^[^a-zA-Z-]/, - phone: /^\+\d+$/, - user_name: /[^a-zA-Za 0-9!"?¨'_.,-]/, - password: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d]+$/, - address: /^[a-zA-Z 0-9/_.,-]*$/, - city: /^[a-zA-Z /_.,-]*$/, - postal_code: /^[a-zA-Z 0-9_.-]{5,10}$/, - company_registration_number: /^[a-zA-Z0-9]{2,20}$/, - url: /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/, - non_empty_string: /^\S.*$/, + email: (value: string) => /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/.test(value), + latin: (value: string) => /[^a-zA-Za 0-9-]/.test(value), + name: (value: string) => + /^(?!.*\s{2,})[\p{L}\s'.-]{2,50}$/u.test(value) && + value.trim().length >= 2 && + value.length <= 50, + phone: (value: string) => /^\+?\d+$/.test(value), + username: (value: string) => /^[A-Za-z0-9_]{3,20}$/.test(value), + password: (value: string) => /^(?=.*[a-z])(?=.*[0-9])(?=.*[A-Z])[ -~]{6,50}$/.test(value), + city: (value: string) => + /^[\p{L}][\p{L}\s'.-]{0,49}$/u.test(value) && + value.trim().length >= 2 && + value.length <= 50, + street: (value: string) => + /^[\p{L}\p{Nd}'.,:;()\\x{b0}@#/-][\p{L}\p{Nd}\s'.,:;()\\x{b0}@#/-]{0,68}$/u.test(value) && + value.trim().length >= 2 && + value.length <= 69, + postal_code: (value: string) => /^[a-zA-Z 0-9-]{2,10}$/.test(value.trim()), + company_registration_number: (value: string) => /^[a-zA-Z0-9]{2,20}$/.test(value), + url: (value: string) => /^[\w_@./:#&+-]+(?:\.[\w]{2,})$/.test(value), + non_empty_string: (value: string) => /^\S.*$/.test(value), } -const validation_is_exceed_number = (input, max_digit) => { - const max_digit_value = max_digit || 15 - return input.length <= max_digit_value -} - -const validation_is_lack_number = (input, min_digit) => input.length + 1 > min_digit - -const emailValidation = (input) => { - if (!input) { - return localize('_t_Email is required_t_') - } else if (!affiliate_validation_regex.email.test(input)) { +const emailValidation = (input: string) => { + if (!input) return localize('_t_Email is required_t_') + else if (!affiliate_validation_regex.email(input)) { return localize('_t_Wrong email_t_') } } -const userNameValidation = (input) => { - if (!input) { - return localize('_t_Username is required_t_') - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') +const userNameValidation = (input: string) => { + if (!input) return localize('_t_Username is required_t_') + else if ( + !affiliate_validation_regex.username(input) || + !affiliate_validation_regex.non_empty_string(input) || + input.length < 2 || + input.length > 20 + ) { + return localize('_t_Please enter 3-20 Latin characters, numbers._t_') } } -const nameValidation = (input, text, min_digit, max_digit) => { +const nameValidation = (input: string, text: string) => { if (!input) { return text + localize('_t_ is required_t_') } else if ( - !validation_is_exceed_number(input, max_digit) || - !validation_is_lack_number(input, min_digit) - ) { - return localize(`_t_You should enter 2-256 characters._t_`) - } else if ( - affiliate_validation_regex.latin.test(input) || - affiliate_validation_regex.name.test(input) + input.length < 2 || + input.length > 50 || + !affiliate_validation_regex.non_empty_string(input) ) { + return localize('_t_You should enter 2-50 characters._t_') + } else if (affiliate_validation_regex.latin(input) || !affiliate_validation_regex.name(input)) { return localize('_t_Only Latin and Alphabet characters_t_') - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') } } -const companyNameValidation = (input, min_digit, max_digit) => { - const length_error = localize(`_t_You should enter 2-256 characters._t_`) - if (!input) { - return localize('_t_Company name is required_t_') - } else if (!/^[a-zA-Z0-9 ]+$/.test(input)) { +const companyNameValidation = (input: string) => { + if (!input) return localize('_t_Company name is required_t_') + else if ( + !/^[a-zA-Z0-9 ]+$/.test(input) || + !affiliate_validation_regex.non_empty_string(input) + ) { return localize('_t_Incorrect company name_t_') - } else if (!validation_is_exceed_number(input, max_digit)) { - return length_error - } else if (!validation_is_lack_number(input, min_digit)) { - return length_error - } else if (affiliate_validation_regex.latin.test(input)) { + } else if (input.trim().length < 2 || input.length > 20) { + return localize('_t_You should enter 2-20 characters._t_') + } else if (affiliate_validation_regex.latin(input)) { return localize('_t_Only Latin characters_t_') - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') } } -const phoneValidation = (input) => { - if (!affiliate_validation_regex.phone.test(input)) { - return localize(`_t_You should enter 8-13 numbers_t_`) +const registrationNumberValidation = (input: string) => { + if (!input) return localize('_t_Company registration number is required_t_') + else if (input.length < 2 || input.length > 20) { + return localize('_t_You should enter 2-20 numbers, characters._t_') + } else if ( + !affiliate_validation_regex.company_registration_number(input) || + !affiliate_validation_regex.non_empty_string(input) + ) { + return localize('_t_Please enter a valid company registration number._t_') + } +} +const phoneValidation = (input: string) => { + if (!affiliate_validation_regex.phone(input)) { + return localize('_t_You should enter 8-13 numbers_t_') } if (!input) { return localize('_t_Mobile number is required_t_') - } else if (!validation_is_exceed_number(input, 14) || !validation_is_lack_number(input, 9)) { - return localize(`_t_You should enter 8-13 numbers._t_`) - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Space not available_t_') + } else if ( + input.length < 8 || + input.length > 13 || + !affiliate_validation_regex.non_empty_string(input) + ) { + return localize('_t_You should enter 8-13 numbers._t_') } } -const passwordValidation = (input, min_digit, max_digit) => { - if (!input) { - return localize('_t_Password is required_t_') +const passwordValidation = (input: string) => { + if (!input) return localize('_t_Password is required_t_') + else if (input.length < 8 || input.length > 50) { + return localize('_t_You should enter 8-50 characters._t_') } else if ( - !validation_is_exceed_number(input, max_digit) || - !validation_is_lack_number(input, min_digit) + !affiliate_validation_regex.password(input) || + !affiliate_validation_regex.non_empty_string(input) ) { - return localize(`_t_You should enter 2-256 characters._t_`) - } else if (!affiliate_validation_regex.password.test(input)) { return localize( - `_t_Password should have lower and uppercase English letters with numbers._t_`, + '_t_Password should have lower and uppercase English letters with numbers._t_', ) - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') } } -const postcodeValidation = (input, min_digit, max_digit) => { - if (!input) { - return localize('_t_Postcode is required_t_') +const postcodeValidation = (input: string) => { + if (!input) return localize('_t_Postcode is required_t_') + else if (input.length < 2 || input.length > 10) { + return localize('_t_You should enter 2-10 numbers, characters._t_') } else if ( - !validation_is_exceed_number(input, max_digit) || - !validation_is_lack_number(input, min_digit) + !affiliate_validation_regex.postal_code(input) || + !affiliate_validation_regex.non_empty_string(input) ) { - return localize(`_t_You should enter 2-256 characters._t_`) - } else if (!affiliate_validation_regex.postal_code.test(input)) { - return localize(`_t_Please enter a valid postcode with Latin characters._t_`) - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') + return localize('_t_Please enter a valid postcode with Latin characters._t_') } } -const registrationNumberValidation = (input) => { - if (!input) { - return localize('_t_Company registration number is required_t_') - } else if (!affiliate_validation_regex.company_registration_number.test(input)) { - return localize(`_t_Please enter a valid company registration number._t_`) - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') - } -} -const streetValidation = (input, text, min_digit, max_digit) => { - if (!input) { - return text - } - if (affiliate_validation_regex.latin.test(input)) { +const streetValidation = (input: string) => { + if (!input) return localize('_t_Street is required_t_') + if (affiliate_validation_regex.latin(input)) { return localize('_t_Only Latin characters_t_') + } else if (input.length < 2 || input.length > 50) { + return localize('_t_You should enter 2-50 characters._t_') } else if ( - !validation_is_exceed_number(input, max_digit) || - !validation_is_lack_number(input, min_digit) + !affiliate_validation_regex.street(input) || + !affiliate_validation_regex.non_empty_string(input) ) { - return localize(`_t_You should enter 2-256 characters._t_`) - } else if (!affiliate_validation_regex.address.test(input)) { return localize('_t_Please enter a valid street_t_') - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') } } -const cityValidation = (input, text, min_digit, max_digit) => { - if (!input) { - return text - } - if (affiliate_validation_regex.latin.test(input)) { +const cityValidation = (input: string) => { + if (!input) return localize('_t_City is required_t_') + if (affiliate_validation_regex.latin(input)) { return localize('_t_Only Latin characters_t_') + } else if (input.length < 2 || input.length > 50) { + return localize('_t_You should enter 2-50 characters._t_') } else if ( - !validation_is_exceed_number(input, max_digit) || - !validation_is_lack_number(input, min_digit) + !affiliate_validation_regex.city(input) || + !affiliate_validation_regex.non_empty_string(input) ) { - return localize(`_t_You should enter 2-256 characters._t_`) - } else if (!affiliate_validation_regex.city.test(input)) { return localize('_t_Please enter a valid city_t_') - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') } } -const urlValidation = (input) => { - if (!affiliate_validation_regex.url.test(input)) { - return localize(`_t_Please enter a valid url_t_`) - } else if (!affiliate_validation_regex.non_empty_string.test(input)) { - return localize('_t_Empty input not available_t_') +const urlValidation = (input: string) => { + if (!input) return localize('_t_Website url is required_t_') + if ( + !affiliate_validation_regex.url(input) || + !affiliate_validation_regex.non_empty_string(input) + ) { + return localize('_t_Please enter a valid url_t_') + } else if (input.length < 2 || input.length > 50) { + return localize('_t_You should enter 2-50 characters._t_') } } const affiliate_validation = { - email: (input) => { - return emailValidation(input) - }, - country: (input) => { + email: (input: string) => emailValidation(input), + city: (input: string) => cityValidation(input), + street: (input: string) => streetValidation(input), + postal_code: (input: string) => postcodeValidation(input), + first_name: (input: string) => nameValidation(input, localize('_t_First Name_t_')), + last_name: (input: string) => nameValidation(input, localize('_t_Last Name_t_')), + phone: (input: string) => phoneValidation(input), + company_name: (input: string) => companyNameValidation(input), + company_registration_number: (input: string) => registrationNumberValidation(input), + website_url: (input: string) => urlValidation(input), + second_website_url: (input: string) => urlValidation(input), + username: (input: string) => userNameValidation(input), + password: (input: string) => passwordValidation(input), + country: (input: any) => { if (!input || input.display_name === '') { return localize('_t_Country is required_t_') } return null }, - city: (input) => { - return cityValidation(input, localize('_t_City is required_t_'), 2, 256) - }, - street: (input) => { - return streetValidation(input, localize('_t_Street is required_t_'), 2, 256) - }, - postal_code: (input) => { - return postcodeValidation(input, 5, 10) - }, - first_name: (input) => { - return nameValidation(input, localize('_t_First Name_t_'), 2, 50) - }, - last_name: (input) => { - return nameValidation(input, localize('_t_Last Name_t_'), 2, 50) - }, - phone: (input) => { - return phoneValidation(input) - }, - company_name: (input) => { - return companyNameValidation(input, 2, 70) - }, - company_registration_number: (input) => { - return registrationNumberValidation(input) - }, - website_url: (input) => { - return urlValidation(input) - }, - second_website_url: (input) => { - return urlValidation(input) - }, - username: (input) => { - return userNameValidation(input) - }, - password: (input) => { - return passwordValidation(input, 6, 50) - }, } export default affiliate_validation diff --git a/src/pages/terms-and-conditions/_business-grid.tsx b/src/pages/terms-and-conditions/_business-grid.tsx index a6392ae8b72..5dfb4890ead 100644 --- a/src/pages/terms-and-conditions/_business-grid.tsx +++ b/src/pages/terms-and-conditions/_business-grid.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { StyledGrid, StyledContainer, IconWrapper, GridCol, Cta } from './_terms-conditions-style' import { Header, Text } from 'components/elements' import { localize, Localize } from 'components/localization' @@ -69,6 +69,23 @@ const BusinessGrid = () => { const bug_bounty_url = `/tnc/business-partners-bug-bounty-es.pdf` const { is_row } = useRegion() const language = getLanguage() + const [show_row_content, setShowRowContent] = useState(true) + const general_terms_url_region = is_row + ? '/tnc/business-partners-general-terms.pdf' + : '/tnc/business-partners-general-terms-eu.pdf' + const affiliate_brokers_url_region = is_row + ? '/tnc/business-partners-affiliates-and-introducing-brokers-row.pdf' + : '/tnc/business-partners-affiliates-and-introducing-brokers-eu.pdf' + const api_user_url_region = is_row + ? '/tnc/business-partners-api-user.pdf' + : '/tnc/business-partners-api-user-eu.pdf' + const bug_bounty_url_region = is_row + ? '/tnc/business-partners-bug-bounty.pdf' + : '/tnc/business-partners-bug-bounty-eu.pdf' + + useEffect(() => { + if (!is_row) setShowRowContent(false) + }, [is_row]) return ( @@ -84,13 +101,7 @@ const BusinessGrid = () => { Icon={General} title="_t_General terms of use_t_" content="_t_Terms and ethical standards for all our affiliates, introducing brokers, API users, and payment agents_t_" - url={ - is_row && language === 'es' - ? general_terms_url - : is_row - ? '/tnc/business-partners-general-terms.pdf' - : '/tnc/business-partners-general-terms-eu.pdf' - } + url={is_row && language === 'es' ? general_terms_url : general_terms_url_region} link_title="_t_General terms of use_t_" /> { url={ is_row && language === 'es' ? affiliate_brokers_url - : is_row - ? '/tnc/business-partners-affiliates-and-introducing-brokers-row.pdf' - : '/tnc/business-partners-affiliates-and-introducing-brokers-eu.pdf' + : affiliate_brokers_url_region } link_title="_t_Affiliates & introducing brokers (IBs)_t_" /> - {is_row && ( + {show_row_content && ( { /> )} diff --git a/src/pages/terms-and-conditions/_clients-grid.tsx b/src/pages/terms-and-conditions/_clients-grid.tsx index d81f40d893f..848aaab7331 100644 --- a/src/pages/terms-and-conditions/_clients-grid.tsx +++ b/src/pages/terms-and-conditions/_clients-grid.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { StyledGrid, StyledContainer, IconWrapper, GridCol, Cta } from './_terms-conditions-style' import { Header, Text } from 'components/elements' import { Localize, localize } from 'components/localization' @@ -27,7 +27,12 @@ type Link = { } const Col = ({ Icon, content, title, eu_links, non_eu_links }: ColProps) => { - const { is_non_eu, is_eu } = useRegion() + const { is_eu } = useRegion() + const [links, setLinks] = useState(non_eu_links) + + useEffect(() => { + if (is_eu) setLinks(eu_links) + }, [is_eu, eu_links]) return ( @@ -40,24 +45,14 @@ const Col = ({ Icon, content, title, eu_links, non_eu_links }: ColProps) => { - {is_non_eu && - non_eu_links?.map((link) => ( - - {localize('_t_pdf - - - - - ))} - {is_eu && - eu_links?.map((link, index) => ( - - {localize('_t_pdf - - - - - ))} + {links?.map((link) => ( + + {localize('_t_pdf + + + + + ))} ) } diff --git a/src/pages/trade-types/cfds/_what_is_cfd.tsx b/src/pages/trade-types/cfds/_what_is_cfd.tsx index 7f63570ad71..b097dcf1ad9 100644 --- a/src/pages/trade-types/cfds/_what_is_cfd.tsx +++ b/src/pages/trade-types/cfds/_what_is_cfd.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { SmallContainer } from '../components/_style' import { SectionContainer } from 'components/containers' import { Header, Text } from 'components/elements' @@ -7,6 +7,11 @@ import useRegion from 'components/hooks/use-region' const WhatIsCFD = () => { const { is_eu } = useRegion() + const [show_eu_content, setShowEuContent] = useState(false) + + useEffect(() => { + if (is_eu) setShowEuContent(true) + }, [is_eu]) return ( @@ -17,7 +22,7 @@ const WhatIsCFD = () => { - {is_eu ? ( + {show_eu_content ? ( diff --git a/src/pages/trade-types/cfds/index.tsx b/src/pages/trade-types/cfds/index.tsx index 7900bff022b..8a39d30c851 100644 --- a/src/pages/trade-types/cfds/index.tsx +++ b/src/pages/trade-types/cfds/index.tsx @@ -9,8 +9,8 @@ import Layout from 'components/layout/layout' import { Localize, WithIntl, localize } from 'components/localization' import { FullWidthMultiColumn } from 'components/elements/full-width-multicolumn' import { StyledBox } from 'pages/markets/static/style/_markets-style' -import useRegion from 'components/hooks/use-region' import { TGatsbyHead } from 'features/types' +import { useShowEuContent } from 'components/hooks/use-show-eu-content' const TradingCFDIncreases = Loadable(() => import('./_trading-cfd-increases')) const StartTrading = Loadable(() => import('./_start-trading')) @@ -18,8 +18,8 @@ const ThingsToKeep = Loadable(() => import('./_mind-when-trading')) const AvailableMarkets = Loadable(() => import('./_available-markets')) const CFD = () => { - const { is_eu } = useRegion() - const content = is_eu ? cfd_content : cfd_content.concat(non_eu_cfd_content) + const show_eu_content = useShowEuContent() + const content = show_eu_content ? cfd_content : cfd_content.concat(non_eu_cfd_content) return ( @@ -43,8 +43,10 @@ const CFD = () => { {content.map(({ alt, src, text, title }) => ( } /> ))} diff --git a/src/pages/trade-types/content/static/_option.tsx b/src/pages/trade-types/content/static/_option.tsx deleted file mode 100644 index dbf51397b23..00000000000 --- a/src/pages/trade-types/content/static/_option.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import Favourite from 'images/svg/trade-types/favourite.svg' -import Instant from 'images/svg/trade-types/instant.svg' -import UserFriendly from 'images/svg/trade-types/user-friendly.svg' -import Flexible from 'images/svg/trade-types/flexible.svg' -import { TString } from 'types/generics' - -type OptionsContentElement = { - src: string - alt: TString - item_title: TString - text: TString -} - -export const digital_options: OptionsContentElement[] = [ - { - src: Favourite, - alt: '_t_favourite markets icon_t_', - item_title: '_t_All favourite markets and more_t_', - text: '_t_Trade on all popular markets plus our proprietary synthetics that are available 24/7._t_', - }, - { - src: Flexible, - alt: '_t_instant access icon_t_', - item_title: '_t_Instant access_t_', - text: '_t_Open an account now and gain access to the world of trading. No need to wait — you can begin trading in minutes._t_', - }, - { - src: Instant, - alt: '_t_user friendly icon_t_', - item_title: '_t_User-friendly platforms with powerful chart widgets_t_', - text: '_t_Trade on secure, intuitive, and easy to use platforms with powerful chart technology._t_', - }, - { - src: UserFriendly, - alt: '_t_flexible icon_t_', - item_title: '_t_Flexible trade types with minimal capital requirements_t_', - text: '_t_Deposit as little as 5 USD to start trading and customise your trades to suit your strategy._t_', - }, -] diff --git a/src/pages/trade-types/options/_how-options-works.tsx b/src/pages/trade-types/options/_how-options-works.tsx deleted file mode 100644 index b1b7c8c5c03..00000000000 --- a/src/pages/trade-types/options/_how-options-works.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import React from 'react' -import { graphql, useStaticQuery } from 'gatsby' -import styled from 'styled-components' -import { SmallContainer, Grid, HowItWorksItem } from '../components/_style' -import SideTab from '../components/_tabs' -import { SectionContainer, Flex, Container } from 'components/containers' -import { Header, Text, QueryImage } from 'components/elements' -import { localize, Localize } from 'components/localization' -import device from 'themes/device' -import DefinePosition from 'images/svg/trade-types/define-your-position.svg' -import GetQuote from 'images/svg/trade-types/get-quote.svg' -import PurchaseContract from 'images/svg/trade-types/purchase-your-contract.svg' - -const query = graphql` - query { - option_market: file(relativePath: { eq: "trade-types/options-market.png" }) { - ...fadeIn - } - option_trade_type: file(relativePath: { eq: "trade-types/options-trade-type.png" }) { - ...fadeIn - } - option_duration: file(relativePath: { eq: "trade-types/options-duration.png" }) { - ...fadeIn - } - option_stake: file(relativePath: { eq: "trade-types/options-stake.png" }) { - ...fadeIn - } - option_quote: file(relativePath: { eq: "trade-types/options-quote.png" }) { - ...fadeIn - } - option_purchase: file(relativePath: { eq: "trade-types/options-purchase.png" }) { - ...fadeIn - } - } -` -const OptionGrid = styled(Grid)` - grid-gap: 2.4rem; -` -const OptionItems = styled(Flex)` - flex-direction: column; - height: auto; - align-items: flex-start; - margin-bottom: 0.8rem; - - @media ${device.mobileL} { - ${Text} { - margin-top: 1.5rem; - } - } -` -const StyledContainer = styled(Container)` - width: 100% !important; -` -const StyledText = styled(Text)` - margin-top: 1.6rem; - - @media ${device.mobileL} { - font-size: 18px; - margin-top: 0; - } -` - -const HowOptionsWorks = () => { - const data = useStaticQuery(query) - - return ( - - - -
- -
- - - -
- {localize('_t_Target -
- - - -
- - - -
- - -
- {localize('_t_Receive -
- - - -
- - - -
- - -
- {localize('_t_Buy -
- - - -
- - - -
-
-
-
- -
-
- -
- - - - - - - - - - - - - - -
- -
- - - - - -
- -
- - - - - -
-
- ) -} - -export default HowOptionsWorks diff --git a/src/pages/trade-types/options/_markets-available.tsx b/src/pages/trade-types/options/_markets-available.tsx deleted file mode 100644 index 29807f7cc39..00000000000 --- a/src/pages/trade-types/options/_markets-available.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import MarketsCarousel from '../components/_markets-carousel' -import LearnMore from '../components/_learn-more' -import { SmallContainer, Card, MarketsItem } from '../components/_style' -import { SectionContainer, Flex } from 'components/containers' -import { Header, Text } from 'components/elements' -import { localize, Localize } from 'components/localization' -import Forex from 'images/svg/trade-types/forex.svg' -import Commodities from 'images/svg/trade-types/commodities.svg' -import Derived from 'images/svg/trade-types/derived.svg' -import StockIndices from 'images/svg/trade-types/stock-indices.svg' - -const MobileCardHeader = styled(Flex)` - margin-bottom: 0.8rem; - flex-direction: column; - height: auto; - - @media (max-width: 680px) { - flex-direction: column; - justify-content: space-between; - align-items: start; - - > img { - width: 48px; - margin: 1.5rem 0; - height: 48px; - } - } -` -const StyledText = styled(Text)` - margin-top: 1.6rem; - font-size: 20px; - - @media (max-width: 680px) { - font-size: 16px; - margin-top: 0; - } -` -const StyledDescription = styled(Text)` - font-size: 14px; - margin-bottom: 2rem; - - @media (max-width: 425px) { - font-size: 12px; - } -` -const StyledCard = styled(Card)` - max-block-size: 30.2rem; -` - -const MarketsAvailable = () => { - return ( - - -
- -
-
- - - - - - {localize('_t_Forex_t_')} - - - - - - - - - - - - - - - - - {localize('_t_Synthetic - - - - - - - - - - - - - - - - {localize('_t_Stocks - - - - - - - - - - - - - - - - - {localize('_t_Commodities_t_')} - - - - - - - - - - - - -
- ) -} - -export default MarketsAvailable diff --git a/src/pages/trade-types/options/_options-to-trade.tsx b/src/pages/trade-types/options/_options-to-trade.tsx deleted file mode 100644 index a371f9d44d5..00000000000 --- a/src/pages/trade-types/options/_options-to-trade.tsx +++ /dev/null @@ -1,364 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import { SmallContainer, OptionGrid, OptionGridSecondary } from '../components/_style' -import Notes from '../components/_notes' -import { Flex, SectionContainer } from 'components/containers' -import { Header, Text } from 'components/elements' -import { localize, Localize } from 'components/localization' -import device from 'themes/device' -// SVG -import RiseFall from 'images/svg/options/rise-fall.svg' -import HigherLower from 'images/svg/options/higher-lower.svg' -import EbEo from 'images/svg/options/eb-eo.svg' -import SbGo from 'images/svg/options/sb-go.svg' -import MatchDiffers from 'images/svg/options/matches-differs.svg' -import EvenOdd from 'images/svg/options/even-odd.svg' -import OverUnder from 'images/svg/options/over-under.svg' -import RcRp from 'images/svg/options/rc-rp.svg' -import HighLowTicks from 'images/svg/options/hl-ticks.svg' -import TnT from 'images/svg/options/tnt.svg' -import Asians from 'images/svg/options/asians.svg' -import OuOd from 'images/svg/options/ou-od.svg' -import HighClose from 'images/svg/options/high-close.svg' -import CloseLow from 'images/svg/options/close-low.svg' -import HighLow from 'images/svg/options/high-low.svg' -import useRegion from 'components/hooks/use-region' - -const MiddleText = styled(Text)` - margin-bottom: 0.8rem; - - @media ${device.tabletL} { - margin-bottom: 1.6rem; - } -` - -const OptionsToTrade = () => { - const { is_eu } = useRegion() - - return ( - - -
- -
-
- -
-
- -
- -
- -
- -
- -
- - - -
- -
- - - {is_eu && ( - - - - )} -
-
- ) -} - -const UpDownGrid = () => { - return ( - - -
- {localize('_t_rise -
- - - - - - - - - - - - - - - -
- -
- {localize('_t_higher -
- - - - - - - - - - - - - - - -
-
- ) -} - -const InOutGrid = () => { - return ( - - -
- {localize('_t_eb -
- - - - - - - - - - - - - - - - -
- -
- {localize('_t_sb -
- - - - - - - - - - - - -
-
- ) -} - -const DigitsGrid = () => { - return ( - - -
- {localize('_t_matches -
- - - - - - - - - - - - -
- -
- {localize('_t_even -
- - - - - - - - - - - - -
- -
- {localize('_t_over -
- - - - - - - - - - - - -
-
- ) -} - -const SingleOptionsGrid = () => { - return ( - - -
- -
-
- {localize('_t_rc -
- - - - - - - - - - - - -
- -
- -
-
- {localize('_t_hl -
- - - - - - - - - -
- -
- -
-
- {localize('_t_tnt_t_')} -
- - - - - - - - - -
- -
- -
-
- {localize('_t_asians_t_')} -
- - - - - - - - - - - - -
- -
- -
-
- {localize('_t_ou -
- - - - - - - - - -
-
- ) -} - -const LookbacksGrid = () => { - return ( - - -
- {localize('_t_high -
- - - - - - -
- -
- {localize('_t_close -
- - - - - - -
- -
- {localize('_t_high -
- - - - - - -
-
- ) -} - -export default OptionsToTrade diff --git a/src/pages/trade-types/options/_start-trading.tsx b/src/pages/trade-types/options/_start-trading.tsx deleted file mode 100644 index 8be205a9b27..00000000000 --- a/src/pages/trade-types/options/_start-trading.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import Timeline from '../components/_timeline' -import { SmallContainer } from '../components/_style' -import { SectionContainer } from 'components/containers' -import { Header } from 'components/elements' -import { Button } from 'components/form' -import { Localize } from 'components/localization' -import Pattern from 'images/common/trade-types/pattern-section.png' -import useHandleSignup from 'components/hooks/use-handle-signup' - -const PatternContainer = styled(SectionContainer)` - background: url(${Pattern}); - background-size: cover; -` - -const FixTimeline = styled(Timeline)` - margin-left: 1.2rem; - margin-bottom: 5rem; -` - -const StartTrading = () => { - const handleSignup = useHandleSignup() - - return ( - - -
- -
- - - - - - - - - - - - -
-
- ) -} - -export default StartTrading diff --git a/src/pages/trade-types/options/_what-are-options.tsx b/src/pages/trade-types/options/_what-are-options.tsx deleted file mode 100644 index 2cd70a55413..00000000000 --- a/src/pages/trade-types/options/_what-are-options.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react' -import { SmallContainer, Ul } from '../components/_style' -import { digital_options } from '../content/static/_option' -import { FullWidthMultiColumn } from 'components/elements/full-width-multicolumn' -import { SectionContainer } from 'components/containers' -import { Header, Text } from 'components/elements' -import { localize, Localize } from 'components/localization' -import { StyledBox } from 'pages/markets/static/style/_markets-style' - -const WhatAreOptions = () => { - return ( - <> - - -
- -
- - - -
- -
- - - -
    -
  • - - ]} - /> - -
  • -
  • - - ]} - /> - -
  • -
-
-
- - {digital_options.map(({ alt, item_title, src, text }) => ( - } - > - ))} - - - ) -} - -export default WhatAreOptions diff --git a/src/pages/trade-types/options/index.tsx b/src/pages/trade-types/options/index.tsx deleted file mode 100644 index e3122d4a6db..00000000000 --- a/src/pages/trade-types/options/index.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import React, { useEffect, useState } from 'react' -import Loadable from '@loadable/component' -import styled from 'styled-components' -import { Hero } from '../components/_style' -import WhatAreTheOptions from './_what-are-options' -import PageNotFound from 'features/pages/404' -import { SEO, SmallContainer, TMetaAttributes } from 'components/containers' -import Layout from 'components/layout/layout' -import CommonHeaderSection from 'components/elements/common-header-section' -import Button from 'components/custom/_button' -import { WithIntl } from 'components/localization' -import { StepperView } from 'components/elements' -import useRegion from 'components/hooks/use-region' -import device from 'themes/device' -import useHandleSignup from 'components/hooks/use-handle-signup' -import { TString } from 'types/generics' -import { TGatsbyHead } from 'features/types' - -const HowOptionsWorks = Loadable(() => import('./_how-options-works')) -const OptionsToTrade = Loadable(() => import('./_options-to-trade')) -const MarketsAvailable = Loadable(() => import('./_markets-available')) - -const meta_attributes: TMetaAttributes = { - og_title: '_t_Options trading | Trading types | Deriv_t_', - og_description: - '_t_Learn about options trading on Deriv. Earn payouts by correctly predicting price movements without needing to buy the underlying assets._t_', -} - -const ButtonContainer = styled.div` - margin-bottom: 16.4rem; - - @media ${device.tablet} { - margin-bottom: 0; - } -` - -const OptionsItems: { title: TString; subtitle: TString }[] = [ - { - title: '_t_Practise_t_', - subtitle: - '_t_Open a demo account and get unlimited virtual funds to practise on our platforms — Deriv Trader, SmartTrader, and Deriv Bot._t_', - }, - { - title: '_t_Trade_t_', - subtitle: '_t_Open a real account, make a deposit, and start trading options for real._t_', - }, - { - title: '_t_Withdraw_t_', - subtitle: - '_t_Conveniently withdraw your funds through any of our supported withdrawal methods._t_', - }, -] - -const Options = () => { - const handleSignup = useHandleSignup() - const { is_row } = useRegion() - const [is_loaded, setLoaded] = useState(false) - - useEffect(() => { - setLoaded(true) - }, []) - - if (is_loaded) { - return is_row ? ( - - - - - - - - - - - -