1import { a as __toESM } from "./rolldown-runtime-Cql5ZV07.js"; 2import { p as require_react } from "./vendor-charts-D81iZKCV.js"; 3import { f as useNavigate, g as require_compiler_runtime, t as require_jsx_runtime, u as useLocation } from "./vendor-react-HZz3WA9p.js"; 4import "./vendor-dnd-D_JGdZnv.js"; 5import "./vendor-mixpanel-Dh8wsiZW.js"; 6import "./device-CBwMusKw.js"; 7import "./vendor-redux-CLEI5hTp.js"; 8import "./vendor-pdf-DksyQ9Qr.js"; 9import "./vendor-utils-DiM3BD4o.js"; 10import "./vendor-ui-G6aSO5L-.js"; 11import { n as toast } from "./dist-Bh07-69G.js"; 12import { G as Plus, Ot as Info, _n as CirclePlus, b as Trash2, n as X, xn as CircleCheckBig } from "./vendor-lucide-EY3Z5fcy.js"; 13import { a as cn, i as Spinner, n as buttonVariants, t as Button } from "./button-BWyXpawe.js"; 14import "./vendor-twilio-BWAG7uEQ.js"; 15import "./app-storage-slice-mFVFfzPf.js"; 16import { i as formatPhone, r as formatCurrency } from "./strings-dAFeDkjR.js"; 17import { S as useWatch, b as useForm, f as objectType, i as arrayType, m as stringType, t } from "./vendor-form-DCqShb_y.js"; 18import "./label-BU8XDazs.js"; 19import { a as AlertDialogDescription, c as AlertDialogTitle, i as AlertDialogContent, n as AlertDialogAction, o as AlertDialogFooter, r as AlertDialogCancel, s as AlertDialogHeader, t as AlertDialog } from "./alert-dialog-DqgZ-9QP.js"; 20import { Yn as trackMethodCall, Z as SelectField, cn as DialogFooter, d as Alert, in as Dialog, m as InputField, on as DialogContent, pr as Separator, rt as FormWrapper } from "./main-DDHJZG-i.js"; 21import "./breadcrumb-DaQ4spt4.js"; 22import { t as AppBreadcrumb } from "./app-breadcrumb-C_0-hj4G.js"; 23import "./area-DK7oSQ7j.js"; 24import { n as FORMATTED_PHONE_REGEX } from "./regex-C8eU81Av.js"; 25import { a as useLazyCheckDriverEmailQuery, i as useInviteDriverMutation, n as useCompanyChangeInviteMutation, t as generateMixed } from "./generate-mixed-BuweQD5H.js"; 26import { C as useInviteDriverUpgradeMutation, a as useCheckDriverSeatsMutation } from "./driver-service-DR_Z8LWd.js"; 27import { t as driver_info_add_default } from "./driver-info-add-BBxWP9yH.js"; 28import { n as DRIVER_TYPE_DATA, o as driverTypeLabelMap, t as DriversTypesPopover } from "./drivers-types-popover-Dopha0y8.js"; 29import "./terminals-service-C5yhnzod.js"; 30import { t as useDriverFormOptions } from "./use-driver-form-options-BVaQhqsQ.js"; 31var import_react = /* @__PURE__ */ __toESM(require_react()); 32var import_jsx_runtime = /* @__PURE__ */ __toESM(require_jsx_runtime()); 33var formatUsdFromCents = (cents) => { 34 return `$${formatCurrency((cents ?? 0) / 100)}`; 35}; 36const DriverUpgradeDialog = ({ open, seatInfo, onOpenChange, onCancel, onSuccessConfirm, upgradePayload, cancelButtonProps, confirmButtonProps, successButtonProps }) => { 37 const [success, setSuccess] = (0, import_react.useState)(false); 38 const [inviteDriverUpgrade, { isLoading: isUpgrading }] = useInviteDriverUpgradeMutation(); 39 (0, import_react.useEffect)(() => { 40 if (!open) setSuccess(false); 41 }, [open]); 42 const addSeats = seatInfo?.addSeats ?? 0; 43 const hasPaymentMethod = Boolean(seatInfo?.paymentMethod); 44 const originAmount = seatInfo?.originAmount ?? 0; 45 const addSeatsPrice = seatInfo?.addSeatsPrice ?? 0; 46 const taxAmount = seatInfo?.taxAmount ?? 0; 47 const dueToday = addSeatsPrice + taxAmount; 48 const totalAmount = seatInfo?.totalAmount ?? 0; 49 const handleConfirmInDriverUpgradeDialog = async () => { 50 trackMethodCall("handleConfirmInDriverUpgradeDialog", []); 51 if (!upgradePayload) return; 52 try { 53 const res = await inviteDriverUpgrade(upgradePayload).unwrap(); 54 if (res.code === 200) setSuccess(true); 55 else toast.error(res.message || "Something went wrong..."); 56 } catch { 57 toast.error("Something went wrong..."); 58 } 59 }; 60 const handleDialogOpenChange = (nextOpen) => { 61 trackMethodCall("handleDialogOpenChange", [nextOpen]); 62 onOpenChange(nextOpen); 63 if (!nextOpen) if (success) onSuccessConfirm?.(); 64 else onCancel?.(); 65 }; 66 const handleConfirmSuccessInDriverUpgradeDialog = () => { 67 trackMethodCall("handleConfirmSuccessInDriverUpgradeDialog", []); 68 onSuccessConfirm?.(); 69 setSuccess(false); 70 onOpenChange(false); 71 }; 72 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog, { 73 open, 74 onOpenChange: handleDialogOpenChange, 75 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogContent, { 76 className: cn("max-w-140 p-5", success && "pt-5"), 77 showCloseButton: !success, 78 "aria-describedby": void 0,
79 children: !success ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { 80 className: "flex flex-col items-center gap-5 p-5", 81 children: [ 82 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("figure", { 83 className: "flex items-center justify-center", 84 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 85 src: driver_info_add_default, 86 alt: "DriverInfoAdd" 87 }) 88 }), 89 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h2", { 90 className: "text-center text-xl font-semibold text-foreground", 91 children: [ 92 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: `You've reached your planâs driver seat limit.` }), 93 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 94 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: `Add ` }), 95 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 96 className: "text-primary", 97 children: addSeats 98 }), 99 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: ` more seats to continue?` }) 100 ] 101 }), 102 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { 103 className: "w-full", 104 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { 105 className: "flex w-full flex-col gap-3 rounded-lg bg-muted px-5 py-6", 106 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { 107 className: "flex w-full flex-col gap-2", 108 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 109 className: "flex w-full items-center justify-between", 110 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 111 className: "text-base font-semibold text-foreground", 112 children: "Due Today" 113 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 114 className: "text-base font-semibold text-foreground", 115 children: !hasPaymentMethod ? "$0.00" : formatUsdFromCents(dueToday) 116 })] 117 }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", { 118 className: "flex w-full flex-col gap-2 text-sm text-foreground", 119 children: [ 120 !hasPaymentMethod && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { 121 className: "flex w-full items-start justify-between", 122 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 123 className: "font-medium", 124 children: "Original Trial Plan" 125 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 126 className: "text-right", 127 children: formatUsdFromCents(originAmount) 128 })] 129 }), 130 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { 131 className: "flex w-full items-start justify-between", 132 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 133 className: "font-medium", 134 children: `+${addSeats}\u00A0Driver Seats` 135 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 136 className: "text-right", 137 children: formatUsdFromCents(addSeatsPrice) 138 })] 139 }), 140 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { 141 className: "flex w-full items-start justify-between", 142 children: hasPaymentMethod ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 143 className: "font-medium", 144 children: "Tax" 145 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 146 className: "text-right", 147 children: formatUsdFromCents(taxAmount) 148 })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 149 className: "font-medium", 150 children: "Total" 151 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 152 className: "text-right", 153 children: formatUsdFromCents(totalAmount) 154 })] }) 155 }) 156 ] 157 })] 158 }
158), hasPaymentMethod ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { 159 className: "flex w-full items-center border-t border-border pt-3", 160 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { 161 className: "text-sm text-muted-foreground", 162 children: ["Payment method: ", seatInfo?.paymentMethod] 163 }) 164 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { 165 className: "flex w-full items-center border-t border-border pt-3", 166 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { 167 className: "text-sm text-muted-foreground", 168 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: `After the trial, NavPro Subscription will cost ` }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 169 className: "font-medium", 170 children: `${formatUsdFromCents(totalAmount)}/month plus tax thereafter.` 171 })] 172 }) 173 })] 174 }) 175 }) 176 ] 177 }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogFooter, { 178 className: "w-full py-0 pb-5", 179 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 180 variant: "outline", 181 ...cancelButtonProps, 182 className: cn("h-9 flex-1", cancelButtonProps?.className), 183 onClick: () => { 184 return onCancel?.(); 185 }, 186 children: "No, Thanks" 187 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 188 ...confirmButtonProps, 189 disabled: confirmButtonProps?.disabled ?? !upgradePayload, 190 loading: confirmButtonProps?.loading ?? isUpgrading, 191 className: cn("h-9 flex-1", confirmButtonProps?.className), 192 onClick: handleConfirmInDriverUpgradeDialog, 193 children: "Confirm Upgrade" 194 })] 195 })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 196 className: "relative flex flex-col items-center gap-3 p-5 py-8 text-center", 197 children: [ 198 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { 199 type: "button", 200 "aria-label": "Close", 201 className: "absolute top-5 right-5 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-hidden", 202 onClick: handleConfirmSuccessInDriverUpgradeDialog, 203 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-5" }) 204 }), 205 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 206 className: "flex items-center justify-center", 207 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleCheckBig, { className: "size-12 text-emerald-500" }) 208 }), 209 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 210 className: "text-lg font-semibold text-foreground", 211 children: "Driver(s) successfully added!" 212 }), 213 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 214 className: "text-sm text-muted-foreground", 215 children: "Your plan has been upgraded. The login credentials have been sent to the driver(s)." 216 }), 217 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 218 type: "button", 219 ...successButtonProps, 220 className: cn("mt-2 w-40", successButtonProps?.className), 221 onClick: handleConfirmSuccessInDriverUpgradeDialog, 222 children: "CLOSE" 223 }) 224 ] 225 }) 226 }) 227 }); 228}; 229var import_compiler_runtime$1 = /* @__PURE__ */ __toESM(require_compiler_runtime()); 230const driverFormSchema = objectType({ 231 firstName: stringType().min(1, "First name is required"), 232 lastName: stringType().min(1, "Last name is required"), 233 phone: stringType().min(1, "Contact number is required").refine((value) => { 234 return FORMATTED_PHONE_REGEX.test(value); 235 }), 236 email: stringType().min(1, "Email is required").email("Please enter a valid email"), 237 password: stringType().min(4, "Password must be at least 4 characters"), 238 permissionGroupId: stringType().optional(), 239 driverType: stringType().optional(), 240 groupId: stringType().optional() 241}); 242const driversNewFormSchema = objectType({ drivers: arrayType(driverFormSchema).min(1, "At least one driver is required") }); 243const useSelectWithAdd = ({ options, fieldName, addRoute, addLabel, addState, form }) => { 244 const navigate = useNavigate(); 245 const fieldKey = (0, import_react.useMemo)(() => { 246 const parts = String(fieldName)?.split("."); 247 return parts[parts.length - 1] || ""; 248 }, [fieldName]); 249 const addValue = (0, import_react.useMemo)(() => { 250 return `add_${fieldKey}`; 251 }, [fieldKey]); 252 const handleChange = (0, import_react.useCallback)((value) => { 253 trackMethodCall("handleChange", [value]); 254 if (value === addValue) { 255 navigate(addRoute, { state: { 256 ...addState, 257 formSnapshot: form.getValues() 258 } }); 259 return; 260 } 261 form.setValue(fieldName, value, { 262 shouldDirty: true, 263 shouldValidate: true 264 }); 265 }, [ 266 addValue, 267 addRoute, 268 navigate, 269 form, 270 fieldName 271 ]); 272 return { 273 options: (0, import_react.useMemo)(() => { 274 return options.length > 0 ? options : [{ 275 value: addValue, 276 label: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 277 className: "flex items-center gap-2", 278 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CirclePlus, { className: "size-4" }
278), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 279 className: "text-primary", 280 children: addLabel 281 })] 282 }) 283 }]; 284 }, [ 285 options, 286 addValue, 287 addLabel 288 ]), 289 onValueChange: handleChange 290 }; 291}; 292var getInviteErrorDetail = (error) => { 293 return error?.data?.detail || "Failed to send invitation"; 294}; 295var setValueOptions = { 296 shouldDirty: true, 297 shouldValidate: true 298}; 299const DriversNewDriverSection = (props) => { 300 const { index, form, driverCount, onDeleteDriver, onInOtherFleetChange } = props; 301 const location = useLocation(); 302 const groupName = location.state?.group; 303 const terminalName = location.state?.terminal; 304 const { terminalOptions, groupOptions } = useDriverFormOptions(); 305 const [checkDriverEmail, { isLoading }] = useLazyCheckDriverEmailQuery(); 306 const [companyChangeInvite, { isLoading: isSendingInvitation }] = useCompanyChangeInviteMutation(); 307 const [isInOtherFleet, setIsInOtherFleet] = (0, import_react.useState)(false); 308 const isPasswordDisabled = useWatch({ 309 control: form.control, 310 name: `drivers.${index}.password` 311 }) === "******"; 312 const invitationFirstName = useWatch({ 313 control: form.control, 314 name: `drivers.${index}.firstName` 315 }); 316 const invitationLastName = useWatch({ 317 control: form.control, 318 name: `drivers.${index}.lastName` 319 }); 320 const invitationPhone = useWatch({ 321 control: form.control, 322 name: `drivers.${index}.phone` 323 }); 324 const isInvitationInfoIncomplete = !invitationFirstName?.trim() || !invitationLastName?.trim() || !invitationPhone?.trim(); 325 const updateDriverFields = (fields, options = setValueOptions) => { 326 Object.entries(fields).forEach(([key, value]) => { 327 if (value !== void 0) form.setValue(`drivers.${index}.${key}`, value, options); 328 }); 329 }; 330 const clearDriverFields = () => { 331 updateDriverFields({ 332 firstName: "", 333 lastName: "", 334 phone: "", 335 password: "" 336 }, { 337 shouldDirty: true, 338 shouldValidate: false 339 }); 340 }; 341 const handleEmailBlur = async (email) => { 342 trackMethodCall("handleEmailBlur", [email]); 343 const emailFieldName = `drivers.${index}.email`; 344 await form.trigger(emailFieldName); 345 if (form.getFieldState(emailFieldName).invalid) return; 346 try { 347 const userInfo = (await checkDriverEmail({ email })).data?.data?.[0]; 348 if (!userInfo) { 349 const randomPassword = generateMixed(); 350 form.setValue(`drivers.${index}.password`, randomPassword, setValueOptions); 351 form.clearErrors(emailFieldName); 352 setIsInOtherFleet(false); 353 onInOtherFleetChange?.(index, false); 354 return; 355 } 356 if (userInfo.invitationCheckStatus === "USER_IN_ANOTHER_TEAM") { 357 const formattedPhone = userInfo.phone ? formatPhone(userInfo.phone, "dash") : ""; 358 updateDriverFields({ 359 firstName: userInfo.first_name || "", 360 lastName: userInfo.last_name || "", 361 phone: formattedPhone, 362 password: "******" 363 }); 364 form.setError(emailFieldName, { 365 type: "manual", 366 message: userInfo.status 367 }); 368 setIsInOtherFleet(true); 369 onInOtherFleetChange?.(index, true); 370 return; 371 } 372 setIsInOtherFleet(false); 373 onInOtherFleetChange?.(index, false); 374 if (userInfo.invitationCheckStatus !== "MIGRATION_ALLOWED") { 375 const formattedPhone_0 = userInfo.phone ? formatPhone(userInfo.phone, "dash") : ""; 376 updateDriverFields({ 377 firstName: userInfo.first_name || "", 378 lastName: userInfo.last_name || "", 379 phone: formattedPhone_0, 380 password: "******" 381 }); 382 form.setError(emailFieldName, { 383 type: "manual", 384 message: userInfo.status 385 }); 386 } else { 387 const randomPassword_0 = generateMixed(); 388 clearDriverFields(); 389 form.clearErrors(emailFieldName); 390 form.setValue(`drivers.${index}.password`, randomPassword_0, setValueOptions); 391 } 392 } catch { 393 toast.error("Something went wrong..."); 394 form.clearErrors(emailFieldName); 395 setIsInOtherFleet(false); 396 onInOtherFleetChange?.(index, false); 397 } 398 }; 399 const handleSendInvitation = async () => { 400 trackMethodCall("handleSendInvitation", []); 401 const driver = form.getValues(`drivers.${index}`); 402 try { 403 await companyChangeInvite({ 404 email: driver.email, 405 phoneNumber: driver.phone.replace(/\D/g, ""), 406 firstName: driver.firstName, 407 lastName: driver.lastName, 408 migrationType: "DRIVER" 409 }).unwrap(); 410 toast.success("Successfully sent an invitation to this driver."); 411 updateDriverFields({ 412 firstName: "", 413 lastName: "", 414 phone: "", 415 password: "", 416 driverType: "", 417 groupId: "" 418 }, { 419 shouldDirty: true, 420 shouldValidate: false 421 }); 422 form.setValue(`drivers.${index}.email`, "", { 423 shouldDirty: true, 424 shouldValidate: false 425 }); 426 form.clearErrors(`drivers.${index}.email`); 427 setIsInOtherFleet(false); 428 onInOtherFleetChange?.(index, false); 429 } catch (error) { 430 toast.error(getInviteErrorDetail(error)); 431 } 432 }; 433 const handleContactNumberChange = (e) => { 434 trackMethodCall("handleContactNumberChange", [e]); 435 const formatted = formatPhone(e.target.value, "dash"); 436 form.setValue(`drivers.${index}.phone`, formatted, { 437 shouldDirty: true, 438 shouldValidate: true 439 }); 440 }; 441 const selectedDriverType = useWatch({ 442 control: form.control, 443 name: `drivers.${index}.driverType` 444 }); 445 const groupSelect = useSelectWithAdd({ 446 options: groupOptions, 447 fieldName: `drivers.${index}.permissionGroupId`, 448 addRoute: "/settings/drivers/groups/new", 449 addState: { from: "addDrivers" }, 450 addLabel: "Add Group", 451 form 452 }); 453 const terminalSelect = useSelectWithAdd({ 454 options: terminalOptions, 455 fieldName: `drivers.${index}.groupId`, 456 addRoute: "/settings/terminals", 457 addState: { from: "addDrivers" }, 458 addLabel: "Add Terminal", 459 form 460 }); 461 (0, import_react.useEffect)(() => { 462 if (groupName || terminalName) { 463 const matchedGroup = groupOptions.find((option) => { 464 return option.label === groupName; 465 }); 466 const matchedTerminal = terminalOptions.find((option_0) => { 467 return option_0.label === terminalName; 468 }); 469 if (matchedGroup) form.setValue(`drivers.${index}.permissionGroupId`, matchedGroup.value, { 470 shouldDirty: true, 471 shouldValidate: true 472 }); 473 if (matchedTerminal) form.setValue(`drivers.${index}.groupId`, matchedTerminal.value, { 474 shouldDirty: true, 475 shouldValidate: true 476 }); 477 } 478 }, [ 479 form, 480 groupName, 481 groupOptions, 482 index, 483 terminalName, 484 terminalOptions 485 ]); 486 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 487 className: "flex flex-col gap-5 rounded-lg border border-border bg-background p-6", 488 children: [
489 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 490 className: "flex items-center justify-between", 491 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { 492 className: "text-lg font-semibold text-accent-foreground", 493 children: ["Driver ", index + 1] 494 }), driverCount > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 495 type: "button", 496 variant: "ghost", 497 size: "icon", 498 className: "size-8", 499 onClick: () => { 500 return onDeleteDriver(index); 501 }, 502 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash2, { className: "size-4 text-destructive" }) 503 })] 504 }), 505 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 506 className: "grid grid-cols-3 gap-6", 507 children: [ 508 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputField, { 509 name: `drivers.${index}.email`, 510 title: "Email Address", 511 type: "email", 512 required: true, 513 onBlur: () => { 514 return handleEmailBlur(form.getValues(`drivers.${index}.email`)); 515 },
516 suffixIcon: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-4 text-primary" }) : null 517 }), 518 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputField, { 519 name: `drivers.${index}.password`, 520 title: "Password", 521 required: true, 522 disabled: isPasswordDisabled 523 }), 524 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectField, { 525 name: `drivers.${index}.permissionGroupId`, 526 title: "Group", 527 placeholder: "Group", 528 options: groupSelect.options, 529 onValueChange: groupSelect.onValueChange 530 }) 531 ] 532 }), 533 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 534 className: "grid grid-cols-3 gap-6", 535 children: [ 536 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputField, { 537 name: `drivers.${index}.firstName`, 538 title: "First Name", 539 required: true 540 }), 541 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputField, { 542 name: `drivers.${index}.lastName`, 543 title: "Last Name", 544 required: true 545 }), 546 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputField, { 547 name: `drivers.${index}.phone`, 548 title: "Contact Number", 549 required: true, 550 inputMode: "numeric", 551 maxLength: 12, 552 onChange: handleContactNumberChange 553 }) 554 ] 555 }), 556 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 557 className: "grid grid-cols-3 gap-6", 558 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 559 className: "flex flex-col space-y-2", 560 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectField, { 561 name: `drivers.${index}.driverType`, 562 title: "Driver Type", 563 placeholder: "Driver Type", 564 options: DRIVER_TYPE_DATA.map((type) => { 565 return { 566 value: type.value,
567 label: type.message ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 568 className: "flex flex-col gap-0.5", 569 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: type.label }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 570 className: "text-xs text-muted-foreground", 571 children: type.message 572 })] 573 }) : type.label 574 }; 575 }), 576 selectValueProps: { children: selectedDriverType ? driverTypeLabelMap[selectedDriverType] || "" : void 0 } 577 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DriversTypesPopover, {})] 578 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectField, { 579 name: `drivers.${index}.groupId`, 580 title: "Terminal", 581 placeholder: "Select terminal", 582 options: terminalSelect.options, 583 onValueChange: terminalSelect.onValueChange 584 })] 585 }), 586 isInOtherFleet && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, { 587 variant: "info", 588 className: "flex items-center justify-between", 589 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 590 className: "flex items-start gap-3", 591 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Info, { className: "mt-0.5 size-4 shrink-0 text-primary" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 592 className: "text-sm font-medium", 593 children: "This driver is currently active in a different fleet. You can send an invitation to the driver to join your fleet." 594 })] 595 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 596 type: "button", 597 size: "sm", 598 className: "ml-3 shrink-0", 599 onClick: handleSendInvitation, 600 disabled: isSendingInvitation || isInvitationInfoIncomplete, 601 children: isSendingInvitation ? "Sending..." : "Send Invitation" 602 })] 603 }) 604 ] 605 }); 606}; 607const DeleteDriverDialog = (props) => { 608 const $ = (0, import_compiler_runtime$1.c)(18); 609 const { open, onOpenChange, onConfirm, onCancel } = props; 610 let t0; 611 if ($[0] === Symbol.for("react.memo_cache_sentinel")) { 612 t0 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogTitle, { children: "Are you sure you want to delete this Driver?" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogDescription, { children: "The Driver will be deleted from Add Drivers list." })] }); 613 $[0] = t0; 614 } else t0 = $[0]; 615 let t1; 616 if ($[1] !== onCancel) { 617 t1 = () => onCancel?.(); 618 $[1] = onCancel; 619 $[2] = t1; 620 } else t1 = $[2]; 621 let t2; 622 if ($[3] === Symbol.for("react.memo_cache_sentinel")) { 623 t2 = cn(buttonVariants({ variant: "outline" })); 624 $[3] = t2; 625 } else t2 = $[3]; 626 let t3; 627 if ($[4] !== t1) { 628 t3 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogCancel, { 629 onClick: t1, 630 className: t2, 631 children: "Cancel" 632 }); 633 $[4] = t1; 634 $[5] = t3; 635 } else t3 = $[5]; 636 let t4; 637 if ($[6] !== onConfirm) { 638 t4 = () => onConfirm?.(); 639 $[6] = onConfirm; 640 $[7] = t4; 641 } else t4 = $[7]; 642 let t5; 643 if ($[8] === Symbol.for("react.memo_cache_sentinel")) { 644 t5 = cn(buttonVariants({ variant: "destructive" })); 645 $[8] = t5; 646 } else t5 = $[8]; 647 let t6; 648 if ($[9] !== t4) { 649 t6 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogAction, { 650 onClick: t4, 651 className: t5, 652 children: "Delete" 653 }); 654 $[9] = t4; 655 $[10] = t6; 656 } else t6 = $[10]; 657 let t7; 658 if ($[11] !== t3 || $[12] !== t6) { 659 t7 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogContent, { children: [t0, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogFooter, { children: [t3, t6] })] }); 660 $[11] = t3; 661 $[12] = t6; 662 $[13] = t7; 663 } else t7 = $[13]; 664 let t8; 665 if ($[14] !== onOpenChange || $[15] !== open || $[16] !== t7) { 666 t8 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialog, { 667 open, 668 onOpenChange, 669 children: t7 670 }); 671 $[14] = onOpenChange; 672 $[15] = open; 673 $[16] = t7; 674 $[17] = t8; 675 } else t8 = $[17]; 676 return t8; 677}; 678var import_compiler_runtime = /* @__PURE__ */ __toESM(require_compiler_runtime()); 679const DriversNewForm = (t0) => { 680 const $ = (0, import_compiler_runtime.c)(42); 681 const { onSubmit, onUnresolvedInvitationChange } = t0; 682 const [deleteDriverDialogOpen, setDeleteDriverDialogOpen] = (0, import_react.useState)(false); 683 const [deleteDriverIndex, setDeleteDriverIndex] = (0, import_react.useState)(0); 684 const formSnapshot = useLocation().state?.formSnapshot; 685 const [driverCount, setDriverCount] = (0, import_react.useState)(formSnapshot?.drivers.length ?? 1); 686 let t1; 687 if ($[0] !== formSnapshot?.drivers.length) { 688 t1 = () => new Array(formSnapshot?.drivers.length ?? 1).fill(false); 689 $[0] = formSnapshot?.drivers.length; 690 $[1] = t1; 691 } else t1 = $[1]; 692 const [inOtherFleetFlags, setInOtherFleetFlags] = (0, import_react.useState)(t1); 693 let t2; 694 let t3; 695 if ($[2] !== inOtherFleetFlags || $[3] !== onUnresolvedInvitationChange) { 696 t2 = () => { 697 onUnresolvedInvitationChange?.(inOtherFleetFlags.some(Boolean)); 698 }; 699 t3 = [inOtherFleetFlags, onUnresolvedInvitationChange]; 700 $[2] = inOtherFleetFlags; 701 $[3] = onUnresolvedInvitationChange; 702 $[4] = t2; 703 $[5] = t3; 704 } else { 705 t2 = $[4]; 706 t3 = $[5]; 707 } 708 (0, import_react.useEffect)(t2, t3); 709 let t4; 710 if ($[6] === Symbol.for("react.memo_cache_sentinel")) { 711 t4 = t(driversNewFormSchema); 712 $[6] = t4; 713 } else t4 = $[6]; 714 let t5; 715 if ($[7] !== formSnapshot) { 716 t5 = formSnapshot ?? { drivers: [{ 717 firstName: "", 718 lastName: "", 719 phone: "", 720 email: "", 721 password: "", 722 permissionGroupId: "", 723 driverType: "", 724 groupId: "" 725 }] }; 726 $[7] = formSnapshot; 727 $[8] = t5; 728 } else t5 = $[8]; 729 let t6; 730 if ($[9] !== t5) { 731 t6 = { 732 resolver: t4, 733 defaultValues: t5, 734 mode: "onChange" 735 }; 736 $[9] = t5; 737 $[10] = t6; 738 } else t6 = $[10]; 739 const form = useForm(t6); 740 let t7; 741 if ($[11] !== form) { 742 t7 = () => { 743 trackMethodCall("handleAddDriver", []); 744 setDriverCount(_temp); 745 setInOtherFleetFlags(_temp2); 746 const currentDrivers = form.getValues("drivers"); 747 form.setValue("drivers", [...currentDrivers, { 748 firstName: "", 749 lastName: "", 750 phone: "", 751 email: "", 752 password: "", 753 permissionGroupId: "", 754 driverType: "", 755 groupId: "" 756 }]); 757 }; 758 $[11] = form; 759 $[12] = t7; 760 } else t7 = $[12]; 761 const handleAddDriver = t7; 762 let t8; 763 if ($[13] !== driverCount || $[14] !== form) { 764 t8 = (index) => { 765 trackMethodCall("handleDeleteDriver", [index]); 766 if (driverCount <= 1) return; 767 setDriverCount(_temp3); 768 setInOtherFleetFlags((prev_2) => prev_2.filter((_, i) => i !== index)); 769 const newDrivers = form.getValues("drivers").filter((__0, i_0) => i_0 !== index); 770 form.setValue("drivers", newDrivers); 771 }; 772 $[13] = driverCount; 773 $[14] = form; 774 $[15] = t8; 775 } else t8 = $[15]; 776 const handleDeleteDriver = t8; 777 let t9; 778 if ($[16] === Symbol.for("react.memo_cache_sentinel")) { 779 t9 = (index_0, value) => { 780 trackMethodCall("handleInOtherFleetChange", [index_0, value]); 781 setInOtherFleetFlags((prev_3) => { 782 const next = [...prev_3]; 783 next[index_0] = value; 784 return next; 785 }); 786 }; 787 $[16] = t9; 788 } else t9 = $[16]; 789 const handleInOtherFleetChange = t9; 790 let t10; 791 if ($[17] !== form || $[18] !== onSubmit) { 792 t10 = form.handleSubmit(onSubmit); 793 $[17] = form; 794 $[18] = onSubmit; 795 $[19] = t10; 796 } else t10 = $[19]; 797 let t11; 798 if ($[20] !== driverCount) { 799 t11 = Array.from({ length: driverCount }); 800 $[20] = driverCount; 801 $[21] = t11; 802 } else t11 = $[21]; 803 let t12; 804 if ($[22] !== driverCount || $[23] !== form || $[24] !== t11) { 805 t12 = t11.map((__1, index_1) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DriversNewDriverSection, { 806 index: index_1, 807 form, 808 driverCount, 809 onDeleteDriver: (index_2) => { 810 setDeleteDriverIndex(index_2); 811 setDeleteDriverDialogOpen(true); 812 }, 813 onInOtherFleetChange: handleInOtherFleetChange 814 }, index_1)); 815 $[22] = driverCount; 816 $[23] = form; 817 $[24] = t11; 818 $[25] = t12; 819 } else t12 = $[25]; 820 let t13; 821 if ($[26] === Symbol.for("react.memo_cache_sentinel")) { 822 t13 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, { className: "size-4" }); 823 $[26] = t13; 824 } else t13 = $[26]; 825 let t14; 826 if ($[27] !== handleAddDriver) { 827 t14 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { 828 type: "button", 829 variant: "default-subtle", 830 onClick: handleAddDriver, 831 className: "self-start", 832 children: [t13, "Add New Driver"] 833 }); 834 $[27] = handleAddDriver; 835 $[28] = t14; 836 } else t14 = $[28]; 837 let t15; 838 if ($[29] !== deleteDriverIndex || $[30] !== handleDeleteDriver) { 839 t15 = () => handleDeleteDriver(deleteDriverIndex); 840 $[29] = deleteDriverIndex; 841 $[30] = handleDeleteDriver; 842 $[31] = t15; 843 } else t15 = $[31]; 844 let t16; 845 if ($[32] === Symbol.for("react.memo_cache_sentinel")) { 846 t16 = () => setDeleteDriverDialogOpen(false); 847 $[32] = t16; 848 } else t16 = $[32]; 849 let t17; 850 if ($[33] !== deleteDriverDialogOpen || $[34] !== t15) { 851 t17 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeleteDriverDialog, { 852 open: deleteDriverDialogOpen, 853 onOpenChange: setDeleteDriverDialogOpen, 854 onConfirm: t15, 855 onCancel: t16 856 }); 857 $[33] = deleteDriverDialogOpen; 858 $[34] = t15; 859 $[35] = t17; 860 } else t17 = $[35]; 861 let t18; 862 if ($[36] !== form || $[37] !== t10 || $[38] !== t12 || $[39] !== t14 || $[40] !== t17) { 863 t18 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FormWrapper, { 864 form, 865 id: "drivers-new-form", 866 onSubmit: t10, 867 className: "flex w-full max-w-[1100px] flex-col space-y-5", 868 children: [ 869 t12, 870 t14, 871 t17 872 ] 873 }); 874 $[36] = form; 875 $[37] = t10; 876 $[38] = t12; 877 $[39] = t14; 878 $[40] = t17; 879 $[41] = t18; 880 } else t18 = $[41]; 881 return t18; 882}; 883function _temp(prev) { 884 return prev + 1; 885} 886function _temp2(prev_0) { 887 return [...prev_0, false]; 888}
889function _temp3(prev_1) { 890 return prev_1 - 1; 891} 892var DriversNew = () => { 893 const [checkDriverSeats, { isLoading: isCheckingSeats }] = useCheckDriverSeatsMutation(); 894 const [inviteDriver] = useInviteDriverMutation(); 895 const navigate = useNavigate(); 896 const [upgradeDialogOpen, setUpgradeDialogOpen] = (0, import_react.useState)(false); 897 const [seatInfo, setSeatInfo] = (0, import_react.useState)(null); 898 const [upgradePayload, setUpgradePayload] = (0, import_react.useState)(); 899 const [hasUnresolvedInvitation, setHasUnresolvedInvitation] = (0, import_react.useState)(false); 900 const handleAddDrivers = async (data) => { 901 trackMethodCall("handleAddDrivers", [data]); 902 try { 903 const emailList = data.drivers.map((driver) => { 904 return driver.email; 905 }); 906 const checkSeatsResult = await checkDriverSeats({ 907 rank: "DRIVER", 908 emailList 909 }).unwrap(); 910 if (checkSeatsResult.code !== 200) { 911 toast.error(checkSeatsResult.message || "Something went wrong..."); 912 return; 913 } 914 const checkData = checkSeatsResult.data ?? null; 915 setSeatInfo(checkData); 916 if ((checkData?.addSeats ?? 0) > 0) { 917 setUpgradePayload({ 918 totalAmount: checkData?.addSeatsPrice ?? 0, 919 taxAmount: checkData?.taxAmount ?? 0, 920 inviteMembers: data.drivers.map((driver_0) => { 921 return { 922 firstName: driver_0.firstName, 923 lastName: driver_0.lastName, 924 email: driver_0.email, 925 password: driver_0.password, 926 phone: driver_0.phone, 927 truckIds: [], 928 trailerIds: [], 929 rank: "DRIVER" 930 }; 931 }) 932 }); 933 setUpgradeDialogOpen(true); 934 return; 935 } 936 const invitePayload = { inviteDrivers: data.drivers.map((driver_1) => { 937 return { 938 firstName: driver_1.firstName, 939 lastName: driver_1.lastName, 940 email: driver_1.email, 941 password: driver_1.password, 942 phone: driver_1.phone, 943 driverType: driver_1.driverType || void 0, 944 permissionGroupId: driver_1.permissionGroupId ? Number(driver_1.permissionGroupId) : void 0, 945 groupId: driver_1.groupId ? Number(driver_1.groupId) : void 0 946 }; 947 }) }; 948 const inviteResult = await inviteDriver(invitePayload).unwrap(); 949 if (inviteResult.successDrivers.length > 0) toast.success(`Successfully invited ${inviteResult.successDrivers.length} driver(s)`); 950 if (inviteResult.causes && inviteResult.causes.length > 0) { 951 const errorMessages = inviteResult.causes.map((cause) => { 952 return `${cause.email}: ${cause.cause}`; 953 }).join("; "); 954 toast.error(errorMessages); 955 } 956 navigate("/settings/drivers"); 957 } catch { 958 toast.error("Failed to submit drivers. Please try again."); 959 } 960 }; 961 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 962 className: "flex h-full flex-col px-5", 963 children: [ 964 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { 965 className: "pt-8 pb-6", 966 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppBreadcrumb, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 967 className: "mt-4 flex items-center justify-between", 968 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 969 className: "flex flex-col space-y-0.5", 970 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { 971 className: "text-2xl font-semibold text-foreground", 972 children: "Add Drivers" 973 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { 974 className: "text-sm text-muted-foreground", 975 children: "Email Address and Password will be used as the primary login info for your driver to log into Trucker Path app." 976 })] 977 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 978 type: "submit", 979 form: "drivers-new-form", 980 loading: isCheckingSeats, 981 disabled: hasUnresolvedInvitation, 982 children: "Save" 983 })] 984 })] 985 }), 986 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator, {}), 987 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 988 className: "flex min-h-0 flex-1 justify-center overflow-y-auto py-6", 989 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DriversNewForm, { 990 onSubmit: handleAddDrivers, 991 onUnresolvedInvitationChange: setHasUnresolvedInvitation 992 }) 993 }),
994 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DriverUpgradeDialog, { 995 open: upgradeDialogOpen, 996 seatInfo, 997 upgradePayload, 998 onOpenChange: setUpgradeDialogOpen, 999 onCancel: () => { 1000 return setUpgradeDialogOpen(false); 1001 }, 1002 onSuccessConfirm: () => { 1003 setUpgradeDialogOpen(false); 1004 navigate("/settings/drivers"); 1005 } 1006 }) 1007 ] 1008 }); 1009}; 1010export { DriversNew };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.