tee3apps-cms-sdk-react 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tee3apps-cms-sdk-react",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Uses JSON to dynamically generate and render UI pages in a website",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/App.css ADDED
@@ -0,0 +1,37 @@
1
+ .main {
2
+ display: flex;
3
+ flex-direction: column;
4
+ }
5
+
6
+ .title {
7
+ display: flex;
8
+ font-weight: bold;
9
+ font-size: 1.875rem; /* 3xl = 30px (1.875rem) */
10
+ justify-content: center;
11
+ padding: 2px;
12
+ }
13
+
14
+ .content-wrapper {
15
+ background-color: #f87171; /* Tailwind's red-400 */
16
+ padding: 1rem; /* 16px */
17
+ }
18
+
19
+ .content-box {
20
+ background-color: white;
21
+ padding: 0.5rem; /* 8px */
22
+ }
23
+
24
+ .image-box {
25
+
26
+ width: 100%;
27
+ /* height: 280px; */
28
+ overflow: hidden;
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ }
33
+
34
+ .fitted-image {
35
+ width: 100%;
36
+ height: 100%;
37
+ }
@@ -79,7 +79,7 @@ interface FontStyle {
79
79
  }
80
80
 
81
81
  interface TitleStyle {
82
- titleText: { all: string;[key: string]: string };
82
+ titleText:any;
83
83
  fontSize: number;
84
84
  fontStyle: FontStyle;
85
85
  fontColor: string;
@@ -209,7 +209,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
209
209
  const offer = calculateOffer(mrp, sp);
210
210
 
211
211
  const cardMode = layout === '1x1' ? 'carousel-mode' : layout === '2x1' ? 'layout-2x1' : 'grid-mode';
212
- const productSlug = product._id;
212
+ const productSlug = product.code;
213
213
  const productLink = `/${productSlug}`;
214
214
 
215
215
  const cardContent = (
@@ -228,7 +228,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
228
228
  <div className="product-header">
229
229
  <div className="product-brand">{product.brand?.name?.all || product.brand?.name}</div>
230
230
  <div className="product-name">{product.name?.all || product.name}</div>
231
- <div className="product-code">Code: {product.code}</div>
231
+ <div className="product-code">Code: {product.sku}</div>
232
232
  </div>
233
233
 
234
234
  {/* Rating - Show first for grid mode */}
@@ -1110,7 +1110,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
1110
1110
  {/* Title */}
1111
1111
  {props.showTitle && (
1112
1112
  <h1 style={getTitleStyle()}>
1113
- {props?.title?.titleText?.all}
1113
+ {props?.title?.titleText}
1114
1114
  </h1>
1115
1115
  )}
1116
1116
 
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import type { ComponentProps } from '../types';
3
+ import './Styles/BooleanField.css'; // Importing the CSS file
4
+
5
+ interface BooleanFieldProps {
6
+ props: ComponentProps;
7
+ value?: any;
8
+ onChange?: (code: string, value: any) => void;
9
+ }
10
+
11
+ const BooleanField: React.FC<BooleanFieldProps> = ({ props, value = false, onChange }) => {
12
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
13
+ if (onChange) {
14
+ const code = props.code || `booleanfield_${props.name?.all || 'field'}`;
15
+ onChange(code, e.target.checked);
16
+ }
17
+ };
18
+
19
+ return (
20
+ <div className="boolean-field">
21
+ <div className="boolean-field__container">
22
+ <div className="boolean-field__checkbox-wrapper">
23
+ <input
24
+ type="checkbox"
25
+ checked={value || false}
26
+ onChange={handleChange}
27
+ className="boolean-field__checkbox"
28
+ required={props.required}
29
+ />
30
+ </div>
31
+ <div className="boolean-field__content">
32
+ <label className="boolean-field__label">
33
+ {props.name?.all || 'Boolean Field'}
34
+ {props.required && <span className="boolean-field__required">*</span>}
35
+ </label>
36
+
37
+ {props.termsandcondition?.all && (
38
+ <p className="boolean-field__terms">
39
+ {props.termsandcondition.all}
40
+ </p>
41
+ )}
42
+
43
+ {props.helperText && (
44
+ <p className="boolean-field__helper-text">{props.helperText}</p>
45
+ )}
46
+
47
+ <div className="boolean-field__status-text">
48
+ {props.onText || 'On'} / {props.offText || 'Off'}
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ );
54
+ };
55
+
56
+ export default BooleanField;
@@ -0,0 +1,229 @@
1
+ import React from 'react';
2
+ import type { Box } from '../types';
3
+ import DateField from './DateField';
4
+ import NumberField from './NumberField';
5
+ import TextComponent from './TextComponent';
6
+ import BooleanField from './BooleanField';
7
+ import Button from './Button';
8
+ import InputField from './InputField';
9
+ import RadioField from './RadioField';
10
+ import SelectField from './SelectField';
11
+ import ImageComponent from './ImageComponent';
12
+
13
+ interface BoxRendererProps {
14
+ box: Box;
15
+ deviceMode?: string;
16
+ autoAdjustForImages?: boolean;
17
+ totalColumns?: number;
18
+ formValues?: Record<string, any>;
19
+ validationErrors?: Record<string, boolean>;
20
+ onFieldChange?: (code: string, value: any) => void;
21
+ onFormSubmit?: () => void;
22
+ }
23
+
24
+ const BoxRenderer: React.FC<BoxRendererProps> = ({
25
+ box,
26
+ deviceMode = 'web',
27
+ autoAdjustForImages = true,
28
+ totalColumns = 12,
29
+ formValues = {},
30
+ validationErrors = {},
31
+ onFieldChange,
32
+ onFormSubmit
33
+ }) => {
34
+ // Get colspan based on device mode
35
+ const getColspan = () => {
36
+ switch(deviceMode) {
37
+ case 'mobileweb':
38
+ return box.props.mode.mobileweb?.colspan || 12;
39
+ case 'mobileapp':
40
+ return box.props.mode.mobileapp?.colspan || 12;
41
+ case 'tablet':
42
+ return box.props.mode.tablet?.colspan || 12;
43
+ case 'web':
44
+ default:
45
+ return box.props.mode.web.colspan || 12;
46
+ }
47
+ };
48
+
49
+ // Get device-specific mode properties
50
+ const getCurrentMode = () => {
51
+ switch(deviceMode) {
52
+ case 'mobileweb':
53
+ return box.props.mode.mobileweb || {};
54
+ case 'mobileapp':
55
+ return box.props.mode.mobileapp || {};
56
+ case 'tablet':
57
+ return box.props.mode.tablet || {};
58
+ case 'web':
59
+ default:
60
+ return box.props.mode.web;
61
+ }
62
+ };
63
+
64
+ const getFieldCode = (component: typeof box.components[0]) => {
65
+ return component.props.code || `${component.name.toLowerCase()}_${component.props.name?.all || 'field'}`;
66
+ };
67
+
68
+ const getFieldValue = (code: string) => {
69
+ return formValues[code] ?? '';
70
+ };
71
+
72
+ const colspan = getColspan();
73
+ const currentMode = getCurrentMode();
74
+ const widthPercentage = (colspan / totalColumns) * 100;
75
+
76
+ // Dynamic height calculation based on content type
77
+ const getBoxHeight = () => {
78
+ if (!autoAdjustForImages) {
79
+ return currentMode.height || 'auto';
80
+ }
81
+
82
+ const hasImageComponent = box.components.some(component =>
83
+ component.name === 'ImageComponent'
84
+ );
85
+
86
+ if (hasImageComponent) {
87
+ return 'auto';
88
+ }
89
+
90
+ return currentMode.height || 'auto';
91
+ };
92
+
93
+ return (
94
+ <div
95
+ style={{
96
+ backgroundColor: box.props.bgColor,
97
+ display: currentMode.isVisible !== false ? 'block' : 'none',
98
+ backgroundSize: box.props.bgsize || 'cover',
99
+ height: getBoxHeight(),
100
+ minHeight: autoAdjustForImages ? 'auto' : (currentMode.height || 'auto'),
101
+ borderRadius: currentMode.radius || '0px',
102
+ width: `${widthPercentage}%`,
103
+ float: 'left',
104
+ boxSizing: 'border-box',
105
+ padding: 'px',
106
+ margin: 0,
107
+ overflow: 'hidden',
108
+ position: 'relative'
109
+ }}
110
+ >
111
+ <div style={{
112
+ width: '100%',
113
+ height: autoAdjustForImages ? 'auto' : '100%',
114
+ display: 'flex',
115
+ flexDirection: 'column',
116
+ alignItems: box.props.align || 'flex-start',
117
+ justifyContent: box.props.justify || 'flex-start',
118
+ padding: 0,
119
+ margin: 0,
120
+ boxSizing: 'border-box'
121
+ }}>
122
+ {box.components.map((component, index) => {
123
+ const getCurrentBoxHeight = () => {
124
+ const validModes = ['web', 'mobileweb', 'mobileapp', 'tablet'] as const;
125
+ const safeDeviceMode = validModes.includes(deviceMode as any)
126
+ ? deviceMode as keyof typeof box.props.mode
127
+ : 'web';
128
+ if (component.name === 'ImageComponent') return 'auto';
129
+ return box.props.mode[safeDeviceMode]?.height || 'auto';
130
+ };
131
+
132
+ if (component.name === 'DateField') {
133
+ const code = getFieldCode(component);
134
+ const hasError = validationErrors[code];
135
+ return (
136
+ <div key={index} style={{ width: '100%' }}>
137
+ <DateField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
138
+ {hasError && component.props.required && (
139
+ <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
140
+ This field is required
141
+ </div>
142
+ )}
143
+ </div>
144
+ );
145
+ } else if (component.name === 'NumberField') {
146
+ const code = getFieldCode(component);
147
+ const hasError = validationErrors[code];
148
+ return (
149
+ <div key={index} style={{ width: '100%' }}>
150
+ <NumberField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
151
+ {hasError && component.props.required && (
152
+ <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
153
+ This field is required
154
+ </div>
155
+ )}
156
+ </div>
157
+ );
158
+ } else if (component.name === 'SelectField') {
159
+ const code = getFieldCode(component);
160
+ const hasError = validationErrors[code];
161
+ return (
162
+ <div key={index} style={{ width: '100%' }}>
163
+ <SelectField props={component.props} value={formValues[code]} onChange={onFieldChange} />
164
+ {hasError && component.props.required && (
165
+ <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
166
+ This field is required
167
+ </div>
168
+ )}
169
+ </div>
170
+ );
171
+ } else if (component.name === 'RadioField') {
172
+ const code = getFieldCode(component);
173
+ const hasError = validationErrors[code];
174
+ return (
175
+ <div key={index} style={{ width: '100%' }}>
176
+ <RadioField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
177
+ {hasError && component.props.required && (
178
+ <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
179
+ This field is required
180
+ </div>
181
+ )}
182
+ </div>
183
+ );
184
+ } else if (component.name === 'InputField') {
185
+ const code = getFieldCode(component);
186
+ const hasError = validationErrors[code];
187
+ return (
188
+ <div key={index} style={{ width: '100%' }}>
189
+ <InputField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
190
+ {hasError && component.props.required && (
191
+ <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
192
+ This field is required
193
+ </div>
194
+ )}
195
+ </div>
196
+ );
197
+ } else if (component.name === 'ImageComponent') {
198
+ return <ImageComponent key={index} props={component.props as any} deviceMode={deviceMode} boxHeight={getCurrentBoxHeight()} />;
199
+ } else if (component.name === 'BooleanField') {
200
+ const code = getFieldCode(component);
201
+ const hasError = validationErrors[code];
202
+ return (
203
+ <div key={index} style={{ width: '100%' }}>
204
+ <BooleanField props={component.props} value={formValues[code] ?? false} onChange={onFieldChange} />
205
+ {hasError && component.props.required && (
206
+ <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
207
+ This field is required
208
+ </div>
209
+ )}
210
+ </div>
211
+ );
212
+ } else if (component.name === 'TextComponent') {
213
+ return <TextComponent key={index} props={component.props} />;
214
+ } else if (component.name === 'ButtonField') {
215
+ return <Button key={index} props={component.props} onFormSubmit={onFormSubmit} />;
216
+ } else {
217
+ return (
218
+ <div key={index} className="mb-4 p-4 bg-gray-100 rounded-md border-2 border-dashed border-gray-300">
219
+ <p className="text-sm text-gray-500">Unknown component: {component.name}</p>
220
+ </div>
221
+ );
222
+ }
223
+ })}
224
+ </div>
225
+ </div>
226
+ );
227
+ };
228
+
229
+ export default BoxRenderer;
@@ -0,0 +1,127 @@
1
+ import React from 'react';
2
+ import type { ComponentProps } from '../types';
3
+
4
+ // Define a proper type for button mode
5
+ interface ButtonModeProps {
6
+ radius?: string;
7
+ bgColor?: string;
8
+ textstyle?: {
9
+ fontSize: number;
10
+ fontColor: string;
11
+ fontStyle: {
12
+ isBold: boolean;
13
+ isItalic: boolean;
14
+ isUnderLine: boolean;
15
+ isStrikeThrough: boolean;
16
+ };
17
+ };
18
+ }
19
+
20
+ interface ButtonProps {
21
+ props: ComponentProps;
22
+ onFormSubmit?: () => void;
23
+ }
24
+
25
+ const Button: React.FC<ButtonProps> = ({ props, onFormSubmit }) => {
26
+ // Get device-specific mode properties with proper typing
27
+ const getCurrentMode = (): ButtonModeProps => {
28
+ // Default to web mode if not specified
29
+ return (props.mode?.web as ButtonModeProps) || {
30
+ radius: '4px',
31
+ bgColor: '#3498db',
32
+ textstyle: {
33
+ fontSize: 16,
34
+ fontColor: '#ffffff',
35
+ fontStyle: {
36
+ isBold: false,
37
+ isItalic: false,
38
+ isUnderLine: false,
39
+ isStrikeThrough: false
40
+ }
41
+ }
42
+ };
43
+ };
44
+
45
+ const currentMode = getCurrentMode();
46
+ const textStyle = currentMode.textstyle || {
47
+ fontSize: 16,
48
+ fontColor: '#ffffff',
49
+ fontStyle: {
50
+ isBold: false,
51
+ isItalic: false,
52
+ isUnderLine: false,
53
+ isStrikeThrough: false
54
+ }
55
+ };
56
+
57
+ // Handle button click
58
+ const handleClick = () => {
59
+ // You can add button click logic here
60
+ console.log('Button clicked:', props.name?.all || 'Button');
61
+
62
+ // Trigger form submission if handler is provided
63
+ if (onFormSubmit) {
64
+ onFormSubmit();
65
+ }
66
+
67
+ // If there's a link configured, handle it
68
+ if (props.linktype === 'EXTERNAL' && props.link?.url) {
69
+ window.open(props.link.url, props.link.target || '_blank');
70
+ }
71
+ };
72
+
73
+ // Get button text - handle both string and {all: string} formats
74
+ const getButtonText = () => {
75
+ if (typeof props.text === 'string') {
76
+ return props.text;
77
+ } else if (props.text?.all) {
78
+ return props.text.all;
79
+ } else if (props.name?.all) {
80
+ return props.name.all;
81
+ }
82
+ return 'Button';
83
+ };
84
+
85
+ return (
86
+ <div className="mb-6">
87
+ <button
88
+ onClick={handleClick}
89
+ disabled={props.disabled}
90
+ style={{
91
+ backgroundColor: currentMode.bgColor || '#3498db',
92
+ color: textStyle.fontColor,
93
+ fontSize: `${textStyle.fontSize}px`,
94
+ fontWeight: textStyle.fontStyle?.isBold ? 'bold' : 'normal',
95
+ fontStyle: textStyle.fontStyle?.isItalic ? 'italic' : 'normal',
96
+ textDecoration: textStyle.fontStyle?.isUnderLine ? 'underline' : 'none',
97
+ textDecorationLine: textStyle.fontStyle?.isStrikeThrough ? 'line-through' : 'none',
98
+ borderRadius: currentMode.radius || '4px',
99
+ padding: '10px 20px',
100
+ border: 'none',
101
+ cursor: props.disabled ? 'not-allowed' : 'pointer',
102
+ opacity: props.disabled ? 0.6 : 1,
103
+ transition: 'all 0.2s ease-in-out',
104
+ minWidth: '120px'
105
+ }}
106
+ onMouseEnter={(e) => {
107
+ if (!props.disabled) {
108
+ e.currentTarget.style.opacity = '0.8';
109
+ e.currentTarget.style.transform = 'translateY(-1px)';
110
+ }
111
+ }}
112
+ onMouseLeave={(e) => {
113
+ if (!props.disabled) {
114
+ e.currentTarget.style.opacity = '1';
115
+ e.currentTarget.style.transform = 'translateY(0)';
116
+ }
117
+ }}
118
+ >
119
+ {getButtonText()}
120
+ </button>
121
+
122
+
123
+ </div>
124
+ );
125
+ };
126
+
127
+ export default Button;
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import type { ComponentProps } from '../types';
3
+ import './Styles/DateField.css'; // Import the external stylesheet
4
+
5
+ interface DateFieldProps {
6
+ props: ComponentProps;
7
+ value?: any;
8
+ onChange?: (code: string, value: any) => void;
9
+ }
10
+
11
+ const DateField: React.FC<DateFieldProps> = ({ props, value = '', onChange }) => {
12
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
13
+ const newValue = e.target.value;
14
+ if (onChange) {
15
+ const code = props.code || `datefield_${props.name?.all || 'field'}`;
16
+ onChange(code, newValue);
17
+ }
18
+ };
19
+
20
+ return (
21
+ <div className="date-field">
22
+ <label className="date-field__label">
23
+ {props.name?.all || 'Date Field'}
24
+ {props.required && <span className="date-field__required">*</span>}
25
+ </label>
26
+
27
+ <input
28
+ type="date"
29
+ value={value || ''}
30
+ onChange={handleChange}
31
+ className="date-field__input"
32
+ required={props.required}
33
+ />
34
+
35
+ {props.helperText && (
36
+ <p className="date-field__helper-text">{props.helperText}</p>
37
+ )}
38
+
39
+ <div className="date-field__pattern">
40
+ Pattern: {props.pattern || 'Default'}
41
+ </div>
42
+ </div>
43
+ );
44
+ };
45
+
46
+ export default DateField;