1+ import { zodResolver } from '@hookform/resolvers/zod' ;
12import { ControlledCurrencyInput } from '@lambdacurry/medusa-forms/controlled/ControlledCurrencyInput' ;
23import type { Meta , StoryObj } from '@storybook/react-vite' ;
34import { FormProvider , useForm } from 'react-hook-form' ;
4- import { zodResolver } from '@hookform/resolvers/zod' ;
55import { z } from 'zod' ;
66
77const meta = {
@@ -11,30 +11,49 @@ const meta = {
1111 layout : 'centered' ,
1212 } ,
1313 tags : [ 'autodocs' ] ,
14+ args : {
15+ symbol : '$' ,
16+ code : 'usd' ,
17+ } ,
1418} satisfies Meta < typeof ControlledCurrencyInput > ;
1519
1620export default meta ;
1721type Story = StoryObj < typeof meta > ;
1822
23+ interface CurrencyFormData {
24+ price : string ;
25+ }
26+
1927// Base wrapper component for stories
20- const CurrencyInputWithHookForm = ( {
21- currency = 'USD' ,
28+ const CurrencyInputWithHookForm = ( {
29+ currency = 'USD' ,
30+ symbol = '$' ,
31+ code = 'usd' ,
2232 schema,
2333 defaultValues = { price : '' } ,
24- ...props
34+ ...props
35+ } : {
36+ currency ?: string ;
37+ symbol ?: string ;
38+ code ?: string ;
39+ schema ?: z . ZodSchema < any > ;
40+ defaultValues ?: CurrencyFormData ;
41+ [ key : string ] : any ;
2542} ) => {
26- const form = useForm ( {
43+ const form = useForm < CurrencyFormData > ( {
2744 resolver : schema ? zodResolver ( schema ) : undefined ,
2845 defaultValues,
2946 } ) ;
3047
3148 return (
3249 < FormProvider { ...form } >
3350 < div className = "w-[400px]" >
34- < ControlledCurrencyInput
35- name = "price"
36- label = "Price"
51+ < ControlledCurrencyInput
52+ name = "price"
53+ label = "Price"
3754 currency = { currency }
55+ symbol = { symbol }
56+ code = { code }
3857 { ...props }
3958 />
4059 </ div >
@@ -44,74 +63,129 @@ const CurrencyInputWithHookForm = ({
4463
4564// 1. Different Currency Symbols
4665export const USDCurrency : Story = {
47- render : ( ) => < CurrencyInputWithHookForm currency = "USD" /> ,
66+ args : {
67+ name : 'price' ,
68+ symbol : '$' ,
69+ code : 'usd' ,
70+ } ,
71+ render : ( args ) => < CurrencyInputWithHookForm currency = "USD" symbol = { args . symbol } code = { args . code } /> ,
4872} ;
4973
5074export const EURCurrency : Story = {
51- render : ( ) => < CurrencyInputWithHookForm currency = "EUR" /> ,
75+ args : {
76+ name : 'price' ,
77+ symbol : '€' ,
78+ code : 'eur' ,
79+ } ,
80+ render : ( args ) => < CurrencyInputWithHookForm currency = "EUR" symbol = { args . symbol } code = { args . code } /> ,
5281} ;
5382
5483export const GBPCurrency : Story = {
55- render : ( ) => < CurrencyInputWithHookForm currency = "GBP" /> ,
84+ args : {
85+ name : 'price' ,
86+ symbol : '£' ,
87+ code : 'gbp' ,
88+ } ,
89+ render : ( args ) => < CurrencyInputWithHookForm currency = "GBP" symbol = { args . symbol } code = { args . code } /> ,
5690} ;
5791
5892// 2. Validation with Min/Max Values
5993const minValidationSchema = z . object ( {
60- price : z . number ( ) . min ( 10 , 'Minimum price is $10' ) ,
94+ price : z . string ( ) . refine ( ( val ) => {
95+ const num = Number . parseFloat ( val ) ;
96+ return ! Number . isNaN ( num ) && num >= 10 ;
97+ } , 'Minimum price is $10' ) ,
6198} ) ;
6299
63100export const MinimumValueValidation : Story = {
64- render : ( ) => (
65- < CurrencyInputWithHookForm
101+ args : {
102+ name : 'price' ,
103+ symbol : '$' ,
104+ code : 'usd' ,
105+ } ,
106+ render : ( args ) => (
107+ < CurrencyInputWithHookForm
66108 currency = "USD"
109+ symbol = { args . symbol }
110+ code = { args . code }
67111 schema = { minValidationSchema }
68- defaultValues = { { price : 5 } }
112+ defaultValues = { { price : '5' } }
69113 label = "Price (Min $10)"
70114 />
71115 ) ,
72116} ;
73117
74118const maxValidationSchema = z . object ( {
75- price : z . number ( ) . max ( 1000 , 'Maximum price is $1000' ) ,
119+ price : z . string ( ) . refine ( ( val ) => {
120+ const num = Number . parseFloat ( val ) ;
121+ return ! Number . isNaN ( num ) && num <= 1000 ;
122+ } , 'Maximum price is $1000' ) ,
76123} ) ;
77124
78125export const MaximumValueValidation : Story = {
79- render : ( ) => (
80- < CurrencyInputWithHookForm
126+ args : {
127+ name : 'price' ,
128+ symbol : '$' ,
129+ code : 'usd' ,
130+ } ,
131+ render : ( args ) => (
132+ < CurrencyInputWithHookForm
81133 currency = "USD"
134+ symbol = { args . symbol }
135+ code = { args . code }
82136 schema = { maxValidationSchema }
83- defaultValues = { { price : 1500 } }
137+ defaultValues = { { price : ' 1500' } }
84138 label = "Price (Max $1000)"
85139 />
86140 ) ,
87141} ;
88142
89143const rangeValidationSchema = z . object ( {
90- price : z . number ( )
91- . min ( 50 , 'Price must be at least $50' )
92- . max ( 500 , 'Price cannot exceed $500' ) ,
144+ price : z . string ( ) . refine ( ( val ) => {
145+ const num = Number . parseFloat ( val ) ;
146+ return ! Number . isNaN ( num ) && num >= 50 && num <= 500 ;
147+ } , 'Price must be between $50 and $500' ) ,
93148} ) ;
94149
95150export const RangeValidation : Story = {
96- render : ( ) => (
97- < CurrencyInputWithHookForm
151+ args : {
152+ name : 'price' ,
153+ symbol : '$' ,
154+ code : 'usd' ,
155+ } ,
156+ render : ( args ) => (
157+ < CurrencyInputWithHookForm
98158 currency = "USD"
159+ symbol = { args . symbol }
160+ code = { args . code }
99161 schema = { rangeValidationSchema }
100- defaultValues = { { price : 25 } }
162+ defaultValues = { { price : '25' } }
101163 label = "Price ($50 - $500)"
102164 />
103165 ) ,
104166} ;
105167
106168// 3. Error Handling and Validation Messages
107169const requiredSchema = z . object ( {
108- price : z . number ( ) . min ( 0.01 , 'Price is required' ) ,
170+ price : z
171+ . string ( )
172+ . min ( 1 , 'Price is required' )
173+ . refine ( ( val ) => {
174+ const num = Number . parseFloat ( val ) ;
175+ return ! Number . isNaN ( num ) && num > 0 ;
176+ } , 'Price must be greater than 0' ) ,
109177} ) ;
110178
111179export const RequiredFieldValidation : Story = {
112- render : ( ) => (
113- < CurrencyInputWithHookForm
180+ args : {
181+ symbol : '$' ,
182+ code : 'usd' ,
183+ } ,
184+ render : ( args ) => (
185+ < CurrencyInputWithHookForm
114186 currency = "USD"
187+ symbol = { args . symbol }
188+ code = { args . code }
115189 schema = { requiredSchema }
116190 label = "Required Price *"
117191 required
@@ -120,50 +194,75 @@ export const RequiredFieldValidation: Story = {
120194} ;
121195
122196const customValidationSchema = z . object ( {
123- price : z . number ( )
124- . min ( 1 , 'Custom error: Price must be at least $1' )
125- . max ( 100 , 'Custom error: Price cannot exceed $100' ) ,
197+ price : z . string ( ) . refine ( ( val ) => {
198+ const num = Number . parseFloat ( val ) ;
199+ return ! Number . isNaN ( num ) && num >= 1 && num <= 100 ;
200+ } , 'Custom error: Price must be between $1 and $100' ) ,
126201} ) ;
127202
128203export const CustomValidationMessage : Story = {
129- render : ( ) => (
130- < CurrencyInputWithHookForm
204+ args : {
205+ symbol : '$' ,
206+ code : 'usd' ,
207+ } ,
208+ render : ( args ) => (
209+ < CurrencyInputWithHookForm
131210 currency = "USD"
211+ symbol = { args . symbol }
212+ code = { args . code }
132213 schema = { customValidationSchema }
133- defaultValues = { { price : 150 } }
214+ defaultValues = { { price : ' 150' } }
134215 label = "Custom Validation Messages"
135216 />
136217 ) ,
137218} ;
138219
139220// 4. Different Currency Codes
140221export const JPYCurrency : Story = {
141- render : ( ) => (
142- < CurrencyInputWithHookForm
143- currency = "JPY"
144- defaultValues = { { price : 11000 } }
222+ args : {
223+ symbol : '¥' ,
224+ code : 'jpy' ,
225+ } ,
226+ render : ( args ) => (
227+ < CurrencyInputWithHookForm
228+ currency = "JPY"
229+ symbol = { args . symbol }
230+ code = { args . code }
231+ defaultValues = { { price : '11000' } }
145232 label = "Price (JPY)"
146233 />
147234 ) ,
148235} ;
149236
150237export const CADCurrency : Story = {
151- render : ( ) => (
152- < CurrencyInputWithHookForm
153- currency = "CAD"
154- defaultValues = { { price : 125.75 } }
238+ args : {
239+ symbol : 'C$' ,
240+ code : 'cad' ,
241+ } ,
242+ render : ( args ) => (
243+ < CurrencyInputWithHookForm
244+ currency = "CAD"
245+ symbol = { args . symbol }
246+ code = { args . code }
247+ defaultValues = { { price : '125.75' } }
155248 label = "Price (CAD)"
156249 />
157250 ) ,
158251} ;
159252
160253export const AUDCurrency : Story = {
161- render : ( ) => (
162- < CurrencyInputWithHookForm
163- currency = "AUD"
164- defaultValues = { { price : 135.50 } }
254+ args : {
255+ name : 'price' ,
256+ symbol : 'A$' ,
257+ code : 'aud' ,
258+ } ,
259+ render : ( args ) => (
260+ < CurrencyInputWithHookForm
261+ currency = "AUD"
262+ symbol = { args . symbol }
263+ code = { args . code }
264+ defaultValues = { { price : '135.50' } }
165265 label = "Price (AUD)"
166266 />
167267 ) ,
168268} ;
169-
0 commit comments