fix: title-case VIES data, animate company info, no price flash
VIES returns ALL CAPS — now title-cased for display. Company info slides in with framer-motion. Price breakdown stays visible during VAT verification instead of flashing to a loading spinner.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from 'react'
|
import { useState, useEffect, useCallback } from 'react'
|
||||||
import { useRouter, useSearchParams } from 'next/navigation'
|
import { useRouter, useSearchParams } from 'next/navigation'
|
||||||
import { motion } from 'framer-motion'
|
import { motion, AnimatePresence } from 'framer-motion'
|
||||||
import { Select } from '@ciphera-net/ui'
|
import { Select } from '@ciphera-net/ui'
|
||||||
import { TRAFFIC_TIERS, PLAN_PRICES } from '@/lib/plans'
|
import { TRAFFIC_TIERS, PLAN_PRICES } from '@/lib/plans'
|
||||||
import { COUNTRY_OPTIONS } from '@/lib/countries'
|
import { COUNTRY_OPTIONS } from '@/lib/countries'
|
||||||
@@ -21,6 +21,11 @@ interface PlanSummaryProps {
|
|||||||
const inputClass =
|
const inputClass =
|
||||||
'w-full rounded-lg border border-neutral-700 bg-neutral-800/50 px-3 py-2.5 text-sm text-white placeholder:text-neutral-500 focus:outline-none focus:ring-1 focus:ring-brand-orange focus:border-brand-orange transition-colors'
|
'w-full rounded-lg border border-neutral-700 bg-neutral-800/50 px-3 py-2.5 text-sm text-white placeholder:text-neutral-500 focus:outline-none focus:ring-1 focus:ring-brand-orange focus:border-brand-orange transition-colors'
|
||||||
|
|
||||||
|
/** Convert VIES ALL-CAPS text to title case (e.g. "SA SODIMAS" → "Sa Sodimas") */
|
||||||
|
function toTitleCase(s: string) {
|
||||||
|
return s.replace(/\S+/g, (w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
export default function PlanSummary({ plan, interval, limit, country, vatId, onCountryChange, onVatIdChange }: PlanSummaryProps) {
|
export default function PlanSummary({ plan, interval, limit, country, vatId, onCountryChange, onVatIdChange }: PlanSummaryProps) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
@@ -148,17 +153,35 @@ export default function PlanSummary({ plan, interval, limit, country, vatId, onC
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* Verified company info */}
|
{/* Verified company info */}
|
||||||
{isVatValid && vatResult?.company_name && (
|
<AnimatePresence>
|
||||||
<div className="mt-2 rounded-lg bg-green-500/5 border border-green-500/20 px-3 py-2 text-xs text-neutral-400">
|
{isVatValid && vatResult?.company_name && (
|
||||||
<p className="font-medium text-green-400">{vatResult.company_name}</p>
|
<motion.div
|
||||||
{vatResult.company_address && (
|
initial={{ opacity: 0, height: 0 }}
|
||||||
<p className="mt-0.5 whitespace-pre-line">{vatResult.company_address}</p>
|
animate={{ opacity: 1, height: 'auto' }}
|
||||||
)}
|
exit={{ opacity: 0, height: 0 }}
|
||||||
</div>
|
transition={{ duration: 0.25, ease: 'easeOut' }}
|
||||||
)}
|
className="overflow-hidden"
|
||||||
{isVatChecked && vatResult && !vatResult.vat_exempt && (
|
>
|
||||||
<p className="mt-1.5 text-xs text-yellow-400">VAT ID could not be verified. 21% VAT will apply.</p>
|
<div className="mt-2 rounded-lg bg-green-500/5 border border-green-500/20 px-3 py-2 text-xs text-neutral-400">
|
||||||
)}
|
<p className="font-medium text-green-400">{toTitleCase(vatResult.company_name)}</p>
|
||||||
|
{vatResult.company_address && (
|
||||||
|
<p className="mt-0.5 whitespace-pre-line">{toTitleCase(vatResult.company_address)}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
{isVatChecked && vatResult && !vatResult.vat_exempt && (
|
||||||
|
<motion.p
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
className="mt-1.5 text-xs text-yellow-400"
|
||||||
|
>
|
||||||
|
VAT ID could not be verified. 21% VAT will apply.
|
||||||
|
</motion.p>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Price breakdown */}
|
{/* Price breakdown */}
|
||||||
@@ -176,10 +199,10 @@ export default function PlanSummary({ plan, interval, limit, country, vatId, onC
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : vatLoading ? (
|
) : vatLoading && !vatResult ? (
|
||||||
<div className="flex items-center gap-2 text-sm text-neutral-400">
|
<div className="flex items-center gap-2 text-sm text-neutral-400">
|
||||||
<div className="h-4 w-4 animate-spin rounded-full border-2 border-neutral-600 border-t-white" />
|
<div className="h-4 w-4 animate-spin rounded-full border-2 border-neutral-600 border-t-white" />
|
||||||
{vatId ? 'Verifying VAT ID...' : 'Calculating VAT...'}
|
Calculating VAT...
|
||||||
</div>
|
</div>
|
||||||
) : vatResult ? (
|
) : vatResult ? (
|
||||||
<div className="space-y-1.5 text-sm">
|
<div className="space-y-1.5 text-sm">
|
||||||
|
|||||||
Reference in New Issue
Block a user