I have created a dynamic quote calculator for a Next.js project that allows users to calculate prices based on word count and selected languages. Currently, the price is calculated using a fixed rate of 0.05 per word.
'use client';
import { useState } from 'react';
import styles from '../styles';
import { allLanguages } from '../constants';
const QuoteContainer = () => {
const [wordCount, setWordCount] = useState('');
const [sourceLanguage, setSourceLanguage] = useState('');
const [targetLanguage, setTargetLanguage] = useState('');
const [totalPrice, setTotalPrice] = useState('');
const handleWordCountChange = (event) => {
setWordCount(event.target.value);
};
const handleSourceLanguageChange = (event) => {
setSourceLanguage(event.target.value);
};
const handleTargetLanguageChange = (event) => {
setTargetLanguage(event.target.value);
};
const handleCalculatePrice = () => {
let priceRate;
switch(parseInt(sourceLanguage)) {
case 1:
priceRate = 0.05;
break;
case 2:
priceRate = 0.06;
break;
case 3:
priceRate = 0.07;
break;
case 4:
priceRate = 0.08;
break;
default:
priceRate = 0.05;
}
const price = Number(wordCount) * priceRate;
setTotalPrice(price.toFixed(2));
};
return (
<section className={`${styles.paddings} mt-0`} id="quote">
<div className="theme-neon relative bg-skin-fill max-w-6xl mt-12 mx-auto overflow-hidden sm:rounded-2xl">
<img className="absolute inset-0 h-full w-full object-cover opacity-30" src="https://images.unsplash.com/photo-1613217784112-e0e197be6a0b?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1600&q=80&sat=-100" alt="People working on laptops" />
<div className="absolute inset-0 bg-gradient-to-br from-skin-hue via-skin-hue to-transparent opacity-90" />
<div className="relative max-w-2xl mx-auto text-center py-16 px-4 sm:py-20 sm:px-6 lg:px-8">
<h2 className="text-3xl font-extrabold text-skin-base sm:text-4xl">
<span className="block">Professional translations made easy.</span>
</h2>
<p className="mt-4 text-md leading-6 text-skin-muted">
<span className="font-extrabold text-gray-300" /> In few clicks, input your order and receive your quote instantly.
</p>
<div className="flex flex-row w-full items-center justify-between">
<div className="flex flex-col w-full mt-6 items-center justify-center text-left">
<div className="flex flex-row w-full">
<div className="mt-12 flex flex-col w-full">
<div className="flex flex-row">
<div className="w-full mr-4 ml-0">
<label htmlFor="InstantQuoteSourceLanguages" className="block mb-2 text-base font-medium text-gray-900 dark:text-white">Source Language</label>
<div className="flex relative z-[1]">
<select
required id="InstantQuoteSourceLanguages"
className="block w-full px-4 py-3 text-base text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
value={sourceLanguage}
onChange={handleSourceLanguageChange}
>
<option value="" disabled>From</option>
{allLanguages
&& allLanguages.map((language) => (
<option
key={`${language.name}-matrix`}
value={[language.group.toString(), language.name]}
>
{language.name}
</option>
))}
</select>
</div>
</div>
<div className="w-full mr-4 ml-0 ">
<label htmlFor="InstantQuoteTargetLanguages" className="block mb-2 text-base font-medium text-gray-900 dark:text-white">Target Language</label>
<div className="flex relative z-[1]">
<select
required id="InstantQuoteTargetLanguages"
className="block w-full px-4 py-3 text-base text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
value={targetLanguage}
onChange={handleTargetLanguageChange}
>
<option value="" disabled>To</option>
{allLanguages
&& allLanguages.map((language) => (
<option
key={language.name}
value={[language.group.toString(), language.name]}
>
{language.name}
</option>
))}
</select>
</div>
</div>
</div>
<div className="relative flex flex-col ml-0 mt-4 w-full self-end min-w-0">
<label htmlFor="InstantQuoteWordCount" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Word count</label>
<input
id="InstantQuoteWordCount"
value={wordCount}
onChange={handleWordCountChange}
type="text"
placeholder="Enter the word count in numbers"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
/>
</div>
<div className="realatie flex flex-col flex-[1] self-end min-w-0 mx-4 my-0 ">
<input
type="submit"
className="text-skin-inverted bg-skin-button-accent hover:bg-skin-button-accent-hover flex items-center justify-center px-4 py-3 mt-4 border border-transparent text-base font-medium rounded-md shadow-sm sm:px-8"
value="Show prices"
onClick={handleCalculatePrice}
/>
</div>
</div>
</div>
<div className="relative flex-[1] flex flex-col items-center mt-6 pt-2 pb-6 px-4">
{totalPrice && (
<div className="flex flex-col max-w-md p-6 space-y-4 divide-y">
<h2 className="text-2xl font-semibold">Quote Summary</h2>
<ul className="flex flex-col pt-4 space-y-2">
<li className="flex items-start justify-between">
<h3>Language:
<span className="text-sm dark:text-violet-400">Source</span>
</h3>
<div className="text-right">
<span>{sourceLanguage}</span>
</div>
</li>
<li className="flex items-start justify-between">
<h3>Language:
<span className="text-sm dark:text-violet-400">Target</span>
</h3>
<div className="text-right">
<span>{targetLanguage}</span>
</div>
</li>
<li className="flex items-start justify-between">
<h3>Word Count
<span className="text-sm dark:text-violet-400">#</span>
</h3>
<div className="text-right">
<span>{wordCount}</span>
</div>
</li>
</ul>
<div className="pt-4 space-y-2">
<div className="flex justify-between">
<span>Rate</span>
<span>$0.50</span>
</div>
<div className="flex items-center space-x-2 text-xs">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" className="w-3 h-3 mt-1 fill-current dark:text-violet-400">
<path d="M485.887,263.261,248,25.373A31.791,31.791,0,0,0,225.373,16H64A48.055,48.055,0,0,0,16,64V225.078A32.115,32.115,0,0,0,26.091,248.4L279.152,486.125a23.815,23.815,0,0,0,16.41,6.51q.447,0,.9-.017a23.828,23.828,0,0,0,16.79-7.734L486.581,296.479A23.941,23.941,0,0,0,485.887,263.261ZM295.171,457.269,48,225.078V64A16.019,16.019,0,0,1,64,48H225.373L457.834,280.462Z"></path>
<path d="M148,96a52,52,0,1,0,52,52A52.059,52.059,0,0,0,148,96Zm0,72a20,20,0,1,1,20-20A20.023,20.023,0,0,1,148,168Z"></path>
</svg>
<span className="dark:text-gray-400">Order until August 31, 2023, get 20% off</span>
</div>
<div className="space-y-6">
<div className="flex justify-between">
<span>Total</span>
<span className="font-semibold">{totalPrice}</span>
</div>
<button type="button" className="w-full py-2 font-semibold border rounded text-skin-inverted bg-skin-button-accent hover:bg-skin-button-accent-hover">Order Now</button>
</div>
</div>
</div>
)}
</div>
<div className="text-sm leading-[26px] mt-[30px]">
<span className="text-lg leading-5 font-medium text-blue-700 align-middle m-0 px-3 py-1.5 rounded-2xl bg-skin-button-accent;">Pay after delivery</span> We trust you: feel free to pay within 5 days from delivery via bank transfer, credit card, or PayPal. <a href="frequently-asked-questions#payments">Learn more</a>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default QuoteContainer;
Now, I want to introduce variations in pricing based on different language groups. For example, I would like to assign different price rates to different language groups: group 1 - $0.05, group 2 - $0.06, group 3 - $0.07, and group 4 - $0.08 as shown below:
const allLanguages = [
{ name: 'Spanish (ES)', group: 1},
{ name: 'Spanish (LATAM)', group: 2 },
{ name: 'US English', group: 3},
{ name: 'English UK', group: 4},
];
How can I modify my existing logic to incorporate this new requirement?