11import React , { useState } from 'react' ;
22import { Link } from 'react-router-dom' ;
3- import { ArrowLeftIcon , PlantIcon } from '@phosphor-icons/react' ;
4- import colors from '../../config/colors' ;
3+ import { AnimatePresence , motion } from 'framer-motion' ;
4+ import {
5+ ArrowLeftIcon ,
6+ PlantIcon ,
7+ ArrowsClockwiseIcon ,
8+ RulerIcon ,
9+ ScalesIcon ,
10+ CalculatorIcon ,
11+ } from '@phosphor-icons/react' ;
512import useSeo from '../../hooks/useSeo' ;
6- import CustomDropdown from '../../components/CustomDropdown' ; // Import CustomDropdown
713import BreadcrumbTitle from '../../components/BreadcrumbTitle' ;
14+ import GenerativeArt from '../../components/GenerativeArt' ;
815
916const BANANA_LENGTH_CM = 18 ; // Average banana length
1017const BANANA_WEIGHT_G = 120 ; // Average banana weight
1118
1219const unitOptions = [
13- { label : 'cm ' , value : 'cm' } ,
14- { label : 'm ' , value : 'm' } ,
15- { label : 'km ' , value : 'km' } ,
16- { label : 'in ' , value : 'in' } ,
17- { label : 'ft ' , value : 'ft' } ,
18- { label : 'g ' , value : 'g' } ,
19- { label : 'kg ' , value : 'kg' } ,
20- { label : 'lb ' , value : 'lb' } ,
21- { label : 'oz ' , value : 'oz' } ,
20+ { label : 'CM ' , value : 'cm' } ,
21+ { label : 'M ' , value : 'm' } ,
22+ { label : 'KM ' , value : 'km' } ,
23+ { label : 'IN ' , value : 'in' } ,
24+ { label : 'FT ' , value : 'ft' } ,
25+ { label : 'G ' , value : 'g' } ,
26+ { label : 'KG ' , value : 'kg' } ,
27+ { label : 'LB ' , value : 'lb' } ,
28+ { label : 'OZ ' , value : 'oz' } ,
2229] ;
2330
2431const BananaConverterPage = ( ) => {
32+ const appName = 'Banana Converter' ;
2533 useSeo ( {
26- title : 'Banana for Scale Converter | Fezcodex' ,
34+ title : ` ${ appName } | Fezcodex` ,
2735 description : 'Convert measuring units into the internet standard: Bananas.' ,
2836 keywords : [
2937 'Fezcodex' ,
@@ -32,11 +40,6 @@ const BananaConverterPage = () => {
3240 'fun' ,
3341 'measurement' ,
3442 ] ,
35- ogTitle : 'Banana Converter | Fezcodex' ,
36- ogDescription : 'Convert any unit of measurement into bananas.' ,
37- twitterCard : 'summary_large_image' ,
38- twitterTitle : 'Banana Converter | Fezcodex' ,
39- twitterDescription : 'Convert any unit of measurement into bananas.' ,
4043 } ) ;
4144
4245 const [ inputValue , setInputValue ] = useState ( '' ) ;
@@ -93,81 +96,174 @@ const BananaConverterPage = () => {
9396 }
9497
9598 if ( isLength ) {
96- setResult ( `${ ( valInCm / BANANA_LENGTH_CM ) . toFixed ( 2 ) } Bananas long ` ) ;
99+ setResult ( `${ ( valInCm / BANANA_LENGTH_CM ) . toFixed ( 2 ) } BANANAS_LONG ` ) ;
97100 } else {
98- setResult ( `${ ( valInG / BANANA_WEIGHT_G ) . toFixed ( 2 ) } Bananas heavy ` ) ;
101+ setResult ( `${ ( valInG / BANANA_WEIGHT_G ) . toFixed ( 2 ) } BANANAS_HEAVY ` ) ;
99102 }
100103 } ;
101104
102- const cardStyle = {
103- backgroundColor : colors [ 'app-alpha-10' ] ,
104- borderColor : colors [ 'app-alpha-50' ] ,
105- color : colors . app ,
106- } ;
107-
108105 return (
109- < div className = "py-16 sm:py-24" >
110- < div className = "mx-auto max-w-7xl px-6 lg:px-8 text-gray-300" >
111- < Link
112- to = "/apps"
113- className = "group text-primary-400 hover:underline flex items-center justify-center gap-2 text-lg mb-4"
114- >
115- < ArrowLeftIcon className = "text-xl transition-transform group-hover:-translate-x-1" /> { ' ' }
116- Back to Apps
117- </ Link >
118- < BreadcrumbTitle title = "Banana Converter" slug = "banana" />
119- < hr className = "border-gray-700" />
120- < div className = "flex justify-center items-center mt-16" >
121- < div
122- className = "group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-between relative transform h-full w-full max-w-2xl"
123- style = { cardStyle }
106+ < div className = "min-h-screen bg-[#050505] text-white selection:bg-emerald-500/30 font-sans" >
107+ < div className = "mx-auto max-w-7xl px-6 py-24 md:px-12" >
108+ < header className = "mb-24" >
109+ < Link
110+ to = "/apps"
111+ className = "group mb-12 inline-flex items-center gap-2 text-xs font-mono text-gray-500 hover:text-white transition-colors uppercase tracking-[0.3em]"
124112 >
125- < div
126- className = "absolute top-0 left-0 w-full h-full opacity-10 rounded-lg overflow-hidden"
127- style = { {
128- backgroundImage :
129- 'radial-gradient(circle, white 1px, transparent 1px)' ,
130- backgroundSize : '10px 10px' ,
131- } }
132- > </ div >
133- < div className = "relative z-10 p-1 text-center" >
134- < h1 className = "text-3xl font-arvo font-normal mb-4 text-app flex items-center justify-center gap-2" >
135- < PlantIcon size = { 32 } /> Banana Converter
136- </ h1 >
137- < hr className = "border-gray-700 mb-6" />
138-
139- < div className = "flex flex-col gap-4 mb-6" >
140- < div className = "flex gap-2" >
141- < input
142- type = "number"
143- value = { inputValue }
144- onChange = { ( e ) => setInputValue ( e . target . value ) }
145- placeholder = "Value"
146- className = "w-full bg-black/20 border border-gray-600 rounded px-3 py-2 focus:outline-none focus:border-yellow-500 transition-colors"
147- />
148- < CustomDropdown
149- options = { unitOptions }
150- value = { inputUnit }
151- onChange = { setInputUnit }
152- label = "Unit"
153- />
113+ < ArrowLeftIcon
114+ weight = "bold"
115+ className = "transition-transform group-hover:-translate-x-1"
116+ />
117+ < span > Applications</ span >
118+ </ Link >
119+
120+ < div className = "flex flex-col md:flex-row md:items-end justify-between gap-12" >
121+ < div className = "space-y-4" >
122+ < BreadcrumbTitle
123+ title = { appName }
124+ slug = "banana"
125+ variant = "brutalist"
126+ />
127+ < p className = "text-xl text-gray-400 max-w-2xl font-light leading-relaxed" >
128+ Standardization protocol. Convert arbitrary metric and imperial
129+ units into the universal banana constant.
130+ </ p >
131+ </ div >
132+ </ div >
133+ </ header >
134+
135+ < div className = "grid grid-cols-1 lg:grid-cols-12 gap-12" >
136+ { /* Main Interaction Area */ }
137+ < div className = "lg:col-span-8 space-y-12" >
138+ < div className = "relative border border-white/10 bg-white/[0.02] p-8 md:p-12 rounded-sm overflow-hidden group" >
139+ < div className = "absolute inset-0 opacity-[0.03] pointer-events-none grayscale" >
140+ < GenerativeArt
141+ seed = { appName + inputValue }
142+ className = "w-full h-full"
143+ />
144+ </ div >
145+
146+ < div className = "relative z-10 space-y-12" >
147+ < div className = "grid grid-cols-1 md:grid-cols-2 gap-8" >
148+ < div className = "space-y-4" >
149+ < label className = "font-mono text-[10px] text-gray-500 uppercase tracking-widest flex items-center gap-2" >
150+ < RulerIcon weight = "fill" /> Input_Value
151+ </ label >
152+ < input
153+ type = "number"
154+ value = { inputValue }
155+ onChange = { ( e ) => setInputValue ( e . target . value ) }
156+ placeholder = "0.00"
157+ className = "w-full bg-black/40 border border-white/10 rounded-sm p-4 font-mono text-xl text-white focus:border-emerald-500/50 outline-none transition-colors"
158+ />
159+ </ div >
160+
161+ < div className = "space-y-4" >
162+ < label className = "font-mono text-[10px] text-gray-500 uppercase tracking-widest flex items-center gap-2" >
163+ < ScalesIcon weight = "fill" /> Unit_Type
164+ </ label >
165+ < div className = "grid grid-cols-3 gap-2" >
166+ { unitOptions . map ( ( opt ) => (
167+ < button
168+ key = { opt . value }
169+ onClick = { ( ) => setInputUnit ( opt . value ) }
170+ className = { `py-2 text-[10px] font-mono uppercase tracking-wider border transition-all ${
171+ inputUnit === opt . value
172+ ? 'bg-emerald-500/10 border-emerald-500 text-emerald-500'
173+ : 'bg-black/40 border-white/10 text-gray-400 hover:border-white/30'
174+ } `}
175+ >
176+ { opt . label }
177+ </ button >
178+ ) ) }
179+ </ div >
180+ </ div >
154181 </ div >
182+
155183 < button
156184 onClick = { handleConvert }
157- className = "px-6 py-2 rounded-md font-arvo font-normal border transition-colors duration-300 hover:bg-yellow-500/20 text-yellow-500 border-yellow-500 "
185+ className = "w-full group relative inline-flex items-center justify-center gap-4 px-10 py-6 bg-white text-black hover:bg-emerald-400 transition-all duration-300 font-mono uppercase tracking-widest text-sm font-black rounded-sm "
158186 >
159- Scale It!
187+ < ArrowsClockwiseIcon
188+ weight = "bold"
189+ size = { 20 }
190+ className = "group-hover:rotate-180 transition-transform duration-500"
191+ />
192+ < span > Compute Scale</ span >
160193 </ button >
161194 </ div >
195+ </ div >
162196
197+ < AnimatePresence >
163198 { result && (
164- < div className = "text-3xl font-bold text-yellow-400 animate-pulse" >
165- { result } 🍌
166- </ div >
199+ < motion . div
200+ initial = { { opacity : 0 , y : 20 } }
201+ animate = { { opacity : 1 , y : 0 } }
202+ exit = { { opacity : 0 , y : 20 } }
203+ className = "relative group border border-emerald-500/20 bg-emerald-500/[0.02] p-8 md:p-12 rounded-sm overflow-hidden"
204+ >
205+ < div className = "flex justify-between items-center mb-6 border-b border-emerald-500/10 pb-6" >
206+ < label className = "font-mono text-[10px] text-emerald-500 uppercase tracking-widest font-black flex items-center gap-2" >
207+ < span className = "h-px w-4 bg-emerald-500/20" /> { ' ' }
208+ Calculated_Output
209+ </ label >
210+ < PlantIcon
211+ size = { 24 }
212+ weight = "fill"
213+ className = "text-yellow-500"
214+ />
215+ </ div >
216+ < div className = "font-mono text-4xl md:text-5xl font-black text-white leading-none tracking-tighter" >
217+ { result } 🍌
218+ </ div >
219+ </ motion . div >
167220 ) }
221+ </ AnimatePresence >
222+ </ div >
223+
224+ { /* Sidebar Info */ }
225+ < div className = "lg:col-span-4 space-y-8" >
226+ < div className = "border border-white/10 bg-white/[0.02] p-8 rounded-sm" >
227+ < h3 className = "font-mono text-[10px] font-bold text-emerald-500 uppercase tracking-widest mb-10 flex items-center gap-2" >
228+ < CalculatorIcon weight = "fill" />
229+ Conversion_Constants
230+ </ h3 >
231+
232+ < div className = "space-y-6" >
233+ < div className = "p-6 border border-white/5 bg-white/[0.01] rounded-sm flex justify-between items-center" >
234+ < span className = "font-mono text-[10px] text-gray-600 uppercase" >
235+ Length_Ref
236+ </ span >
237+ < p className = "text-white font-mono text-xs font-bold uppercase tracking-tight" >
238+ { BANANA_LENGTH_CM } CM
239+ </ p >
240+ </ div >
241+ < div className = "p-6 border border-white/5 bg-white/[0.01] rounded-sm flex justify-between items-center" >
242+ < span className = "font-mono text-[10px] text-gray-600 uppercase" >
243+ Mass_Ref
244+ </ span >
245+ < p className = "text-white font-mono text-xs font-bold uppercase tracking-tight" >
246+ { BANANA_WEIGHT_G } G
247+ </ p >
248+ </ div >
249+ </ div >
250+ </ div >
251+
252+ < div className = "p-8 border border-white/10 bg-white/[0.01] rounded-sm flex items-start gap-4" >
253+ < PlantIcon size = { 24 } className = "text-gray-700 shrink-0 mt-1" />
254+ < p className = "text-[10px] font-mono uppercase tracking-[0.2em] leading-relaxed text-gray-500" >
255+ The Banana Standard is the only universally accepted measurement
256+ system for internet-scale visual verification. All calculations
257+ assume a standard cavendish curve topology.
258+ </ p >
168259 </ div >
169260 </ div >
170261 </ div >
262+
263+ < footer className = "mt-32 pt-12 border-t border-white/10 flex flex-col md:flex-row justify-between items-center gap-6 text-gray-600 font-mono text-[10px] uppercase tracking-[0.3em]" >
264+ < span > Fezcodex_Scale_Engine_v0.9.4</ span >
265+ < span className = "text-gray-800" > SYSTEM_STATUS // CALIBRATED</ span >
266+ </ footer >
171267 </ div >
172268 </ div >
173269 ) ;
0 commit comments