@apptimate/ui 5.4.0 → 5.6.0

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": "@apptimate/ui",
3
- "version": "5.4.0",
3
+ "version": "5.6.0",
4
4
  "main": "src/index.tsx",
5
5
  "types": "src/index.tsx",
6
6
  "dependencies": {
@@ -8,6 +8,7 @@
8
8
  "apexcharts": "^5.15.2",
9
9
  "class-variance-authority": "^0.7.1",
10
10
  "clsx": "^2.1.1",
11
+ "date-fns": "^4.4.0",
11
12
  "framer-motion": "^12.38.0",
12
13
  "lucide-react": "^1.14.0",
13
14
  "react": "^19.2.5",
@@ -49,6 +49,10 @@ export function PartyPicker({
49
49
  const [quickAddLastName, setQuickAddLastName] = useState("");
50
50
  const [quickAddEmail, setQuickAddEmail] = useState("");
51
51
  const [quickAddPhone, setQuickAddPhone] = useState("");
52
+ const [quickAddSecondaryContact, setQuickAddSecondaryContact] = useState("");
53
+ const [quickAddGender, setQuickAddGender] = useState("");
54
+ const [quickAddDOB, setQuickAddDOB] = useState("");
55
+ const [errors, setErrors] = useState<Record<string, string[]>>({});
52
56
  const [isCreating, setIsCreating] = useState(false);
53
57
 
54
58
  const fetchData = useCallback(async (query: string = "") => {
@@ -90,12 +94,16 @@ export function PartyPicker({
90
94
  const handleQuickAdd = async () => {
91
95
  if (!quickAddFirstName.trim()) return;
92
96
  setIsCreating(true);
97
+ setErrors({});
93
98
  try {
94
99
  const payload = {
95
100
  first_name: quickAddFirstName.trim(),
96
101
  last_name: quickAddLastName.trim() || undefined,
97
102
  email: quickAddEmail.trim() || undefined,
98
103
  primary_contact: quickAddPhone.trim() || undefined,
104
+ secondary_contact: quickAddSecondaryContact.trim() || undefined,
105
+ gender: quickAddGender || undefined,
106
+ date_of_birth: quickAddDOB || undefined,
99
107
  type: [partyType === "all" ? "customer" : partyType],
100
108
  status: "active"
101
109
  };
@@ -110,7 +118,13 @@ export function PartyPicker({
110
118
  setQuickAddLastName("");
111
119
  setQuickAddEmail("");
112
120
  setQuickAddPhone("");
121
+ setQuickAddSecondaryContact("");
122
+ setQuickAddGender("");
123
+ setQuickAddDOB("");
124
+ setErrors({});
113
125
  setIsOpen(false);
126
+ } else if ((res as any).errors) {
127
+ setErrors((res as any).errors);
114
128
  } else {
115
129
  toast.error(res.message || "Failed to create");
116
130
  }
@@ -157,6 +171,10 @@ export function PartyPicker({
157
171
  setQuickAddLastName("");
158
172
  setQuickAddEmail("");
159
173
  setQuickAddPhone("");
174
+ setQuickAddSecondaryContact("");
175
+ setQuickAddGender("");
176
+ setQuickAddDOB("");
177
+ setErrors({});
160
178
  }}
161
179
  className="p-1.5 rounded-lg bg-primary-50 text-primary-600 hover:bg-primary-100 transition-colors flex-shrink-0"
162
180
  title={`Quick Add ${label}`}
@@ -207,12 +225,14 @@ export function PartyPicker({
207
225
  placeholder={`Enter ${label.toLowerCase()} first name`}
208
226
  value={quickAddFirstName}
209
227
  onChange={(e) => setQuickAddFirstName(e.target.value)}
228
+ error={errors.first_name?.[0]}
210
229
  />
211
230
  <Input
212
231
  label="Last Name"
213
232
  placeholder={`Enter ${label.toLowerCase()} last name`}
214
233
  value={quickAddLastName}
215
234
  onChange={(e) => setQuickAddLastName(e.target.value)}
235
+ error={errors.last_name?.[0]}
216
236
  />
217
237
  </div>
218
238
  <div className="grid grid-cols-2 gap-3">
@@ -222,14 +242,47 @@ export function PartyPicker({
222
242
  placeholder="Email address"
223
243
  value={quickAddEmail}
224
244
  onChange={(e) => setQuickAddEmail(e.target.value)}
245
+ error={errors.email?.[0]}
225
246
  />
226
247
  <Input
227
- label="Phone"
228
- placeholder="Phone number"
248
+ label="Primary Contact"
249
+ placeholder="Primary phone number"
229
250
  value={quickAddPhone}
230
251
  onChange={(e) => setQuickAddPhone(e.target.value)}
252
+ error={errors.primary_contact?.[0]}
231
253
  />
232
254
  </div>
255
+ <div className="grid grid-cols-2 gap-3">
256
+ <Input
257
+ label="Secondary Contact"
258
+ placeholder="Alternative phone (optional)"
259
+ value={quickAddSecondaryContact}
260
+ onChange={(e) => setQuickAddSecondaryContact(e.target.value)}
261
+ error={errors.secondary_contact?.[0]}
262
+ />
263
+ <Input
264
+ label="Date of Birth"
265
+ type="date"
266
+ value={quickAddDOB}
267
+ onChange={(e) => setQuickAddDOB(e.target.value)}
268
+ error={errors.date_of_birth?.[0]}
269
+ />
270
+ </div>
271
+ <div className="space-y-1">
272
+ <label className="text-sm font-semibold text-gray-700">Gender</label>
273
+ <select
274
+ value={quickAddGender}
275
+ onChange={(e) => setQuickAddGender(e.target.value)}
276
+ className="w-full rounded-lg border border-gray-200 px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white"
277
+ >
278
+ <option value="">Select gender</option>
279
+ <option value="male">Male</option>
280
+ <option value="female">Female</option>
281
+ <option value="other">Other</option>
282
+ <option value="prefer_not_to_say">Prefer not to say</option>
283
+ </select>
284
+ {errors.gender?.[0] && <p className="text-xs text-red-500">{errors.gender[0]}</p>}
285
+ </div>
233
286
  <ModalFooter>
234
287
  <Button
235
288
  variant="flat"