diff --git a/client/src/containers/User/AvailableTable/AvailableTable.tsx b/client/src/containers/User/AvailableTable/AvailableTable.tsx index ebadde6..99f63fe 100644 --- a/client/src/containers/User/AvailableTable/AvailableTable.tsx +++ b/client/src/containers/User/AvailableTable/AvailableTable.tsx @@ -3,6 +3,7 @@ import axios from "axios"; import { Link } from "react-router-dom"; import styles from "./AvailableTable.module.css"; import Table from "./Table"; +import DriversTable from "./DriversTable"; // ====================================================== // TYPES @@ -72,11 +73,126 @@ interface Load { interface Driver { id?: string; + + firstName?: string; + lastName?: string; + displayName?: string; + profilePhoto?: string; + description?: string; company?: string; + + archived?: boolean; + status?: string; + + phoneNumber?: string; + alternatePhone?: string; + email?: string; + preferredContactMethod?: string; + website?: string; + + city?: string; + state?: string; + zipCode?: string; + country?: string; + + currentLocationCity?: string; + currentLocationState?: string; + + willingToRelocate?: boolean; + willingToTravelNationwide?: boolean; + + driverType?: string; + vehicleType?: string; + availableNow?: boolean; + + hasCDL?: boolean; + cdlClass?: string; + + licenseNumber?: string; + licenseState?: string; + licenseExpirationDate?: string; + + hazmatEndorsement?: boolean; + tankerEndorsement?: boolean; + doublesTriplesEndorsement?: boolean; + passengerEndorsement?: boolean; + schoolBusEndorsement?: boolean; + + twicCard?: boolean; + passportReady?: boolean; + + yearsExperience?: number; + + accidentsLast3Years?: number; + movingViolationsLast3Years?: number; + + duiHistory?: boolean; + felonyHistory?: boolean; + + dryVanExperience?: boolean; + reeferExperience?: boolean; + flatbedExperience?: boolean; + stepDeckExperience?: boolean; + rgnExperience?: boolean; + + hotshotExperience?: boolean; + boxTruckExperience?: boolean; + straightTruckExperience?: boolean; + cargoVanExperience?: boolean; + sprinterVanExperience?: boolean; + + employmentType?: string; + + desiredPay?: number; + payType?: string; + + availableDate?: string; + + currentlyEmployed?: boolean; + + prefersLocal?: boolean; + prefersRegional?: boolean; + prefersOTR?: boolean; + + preferredHomeTime?: string; + preferredStates?: string; + maxDistanceFromHome?: number; + + medicalCardExpiration?: string; + + clearinghouseRegistered?: boolean; + sapCompleted?: boolean; + + ownerOperator?: boolean; + ownsTruck?: boolean; + + truckYear?: number; + truckMake?: string; + truckModel?: string; + + truckType?: string; + trailerType?: string; + + rating?: number; + + completedJobs?: number; + cancelledJobs?: number; + noShows?: number; + + emailVerified?: boolean; + phoneVerified?: boolean; + identityVerified?: boolean; + + backgroundCheckVerified?: boolean; + insuranceVerified?: boolean; + userId?: string; } +// const LOAD_KEYS = Object.keys(defaultLoad); +// const DRIVER_KEYS = Object.keys(defaultDriver); + // ====================================================== // DEFAULT LOAD // ====================================================== @@ -138,16 +254,28 @@ const defaultLoad: Load = { company: "", }; -const normalizeDate = ( - value?: string | null -) => { - if (!value || value.trim() === "") { - return null; - } +// const normalizeDate = ( +// value?: string | null +// ) => { +// if (!value || value.trim() === "") { +// return null; +// } + +// const date = new Date(value); + +// if (isNaN(date.getTime())) { +// return null; +// } + +// return date.toISOString(); +// }; +const normalizeDate = (value?: string | null) => { + if (!value || value.trim() === "") return null; const date = new Date(value); if (isNaN(date.getTime())) { + console.warn("Invalid date:", value); return null; } @@ -160,12 +288,16 @@ const normalizeDate = ( const AvailableTable: React.FC = () => { const API_BASE = process.env.REACT_APP_API_BASE_URL || "http://localhost:3001"; + // const API_BASE = React.useMemo( + // () => process.env.REACT_APP_API_BASE_URL || "http://localhost:3001", + // [] + // ); const [loads, setLoads] = useState([]); - const [drivers, setDrivers] = useState([]); + const [drivers, setDrivers] = useState([]); const [userLoads, setUserLoads] = useState([]); - const [userDrivers, setUserDrivers] = useState([]); + const [userDrivers, setUserDrivers] = useState([]); const [loadFilters, setLoadFilters] = useState({ search: "", @@ -187,15 +319,135 @@ const AvailableTable: React.FC = () => { const [driverFilters, setDriverFilters] = useState({ search: "", company: "", - description: "", + city: "", + state: "", + driverType: "", + vehicleType: "", + hasCDL: "", + cdlClass: "", + ownerOperator: "", + availableNow: "", }); const [newLoad, setNewLoad] = useState(defaultLoad); - const [newDriver, setNewDriver] = useState({ + const defaultDriver: Driver = { + firstName: "", + lastName: "", + displayName: "", + profilePhoto: "", + description: "", company: "", - }); + + status: "AVAILABLE", + + phoneNumber: "", + alternatePhone: "", + email: "", + preferredContactMethod: "", + website: "", + + city: "", + state: "", + zipCode: "", + country: "USA", + + currentLocationCity: "", + currentLocationState: "", + + willingToRelocate: false, + willingToTravelNationwide: false, + + driverType: "DELIVERY", + vehicleType: "", + + availableNow: true, + + hasCDL: false, + cdlClass: "", + + licenseNumber: "", + licenseState: "", + licenseExpirationDate: "", + + hazmatEndorsement: false, + tankerEndorsement: false, + doublesTriplesEndorsement: false, + passengerEndorsement: false, + schoolBusEndorsement: false, + + twicCard: false, + passportReady: false, + + yearsExperience: 0, + + accidentsLast3Years: 0, + movingViolationsLast3Years: 0, + + duiHistory: false, + felonyHistory: false, + + dryVanExperience: false, + reeferExperience: false, + flatbedExperience: false, + stepDeckExperience: false, + rgnExperience: false, + + hotshotExperience: false, + boxTruckExperience: false, + straightTruckExperience: false, + cargoVanExperience: false, + sprinterVanExperience: false, + + employmentType: "", + + desiredPay: 0, + payType: "", + + availableDate: "", + + currentlyEmployed: false, + + prefersLocal: false, + prefersRegional: false, + prefersOTR: false, + + preferredHomeTime: "", + preferredStates: "", + maxDistanceFromHome: 0, + + medicalCardExpiration: "", + + clearinghouseRegistered: false, + sapCompleted: false, + + ownerOperator: false, + ownsTruck: false, + + truckYear: 0, + truckMake: "", + truckModel: "", + + truckType: "", + trailerType: "", + + rating: 0, + + completedJobs: 0, + cancelledJobs: 0, + noShows: 0, + + emailVerified: false, + phoneVerified: false, + identityVerified: false, + + backgroundCheckVerified: false, + insuranceVerified: false, + }; + + const [newDriver, setNewDriver] = + useState(defaultDriver); useEffect(() => { console.log( @@ -225,7 +477,7 @@ const AvailableTable: React.FC = () => { const userId = localStorage.getItem("userId"); if (userId) { - setUserDrivers(data.filter((d: any) => d.userId === userId)); + setUserDrivers(data.filter((d: Driver) => d.userId === userId)); } }, [API_BASE]); @@ -238,11 +490,31 @@ const AvailableTable: React.FC = () => { // LOAD FILTER (FULL FIELD SUPPORT) // ====================================================== const filteredLoads = loads.filter((l) => { - const q = loadFilters.search.toLowerCase(); + // const q = loadFilters.search.toLowerCase(); + const q = (loadFilters.search || "").toLowerCase(); + // const matchesGlobal = + // l.postReference?.toLowerCase().includes(q) || + // l.originCity?.toLowerCase().includes(q) || + // l.destinationCity?.toLowerCase().includes(q) || + // l.brokerName?.toLowerCase().includes(q); return ( - (!q || JSON.stringify(l).toLowerCase().includes(q)) && + (!q || + [ + l.postReference, + l.originCity, + l.originState, + l.destinationCity, + l.destinationState, + l.brokerName, + l.loadSource + ] + .filter(Boolean) + .join(" ") + .toLowerCase() + .includes(q) + ) && (!loadFilters.postReference || l.postReference?.toLowerCase().includes(loadFilters.postReference.toLowerCase())) && (!loadFilters.originCity || @@ -276,14 +548,76 @@ const AvailableTable: React.FC = () => { // DRIVER FILTER // ====================================================== const filteredDrivers = drivers.filter((d: Driver) => { - const q = driverFilters.search.toLowerCase(); + // const q = + // driverFilters.search.toLowerCase(); + const q = (driverFilters.search || "").toLowerCase(); + + const normalizeBool = (val: any) => { + if (val === true || val === "true" || val === 1 || val === "1") return "true"; + if (val === false || val === "false" || val === 0 || val === "0") return "false"; + return ""; + }; return ( - (!q || JSON.stringify(d).toLowerCase().includes(q)) && + (!q || + JSON.stringify(d) + .toLowerCase() + .includes(q)) && + (!driverFilters.company || - d.company?.toLowerCase().includes(driverFilters.company.toLowerCase())) && - (!driverFilters.description || - d.description?.toLowerCase().includes(driverFilters.description.toLowerCase())) + d.company + ?.toLowerCase() + .includes( + driverFilters.company.toLowerCase() + )) && + + (!driverFilters.city || + d.city + ?.toLowerCase() + .includes( + driverFilters.city.toLowerCase() + )) && + + (!driverFilters.state || + d.state + ?.toLowerCase() + .includes( + driverFilters.state.toLowerCase() + )) && + + (!driverFilters.driverType || + d.driverType + ?.toLowerCase() + .includes( + driverFilters.driverType.toLowerCase() + )) && + + (!driverFilters.vehicleType || + d.vehicleType + ?.toLowerCase() + .includes( + driverFilters.vehicleType.toLowerCase() + )) && + + // (!driverFilters.hasCDL || + // String(d.hasCDL) === driverFilters.hasCDL) && + (!driverFilters.hasCDL || + normalizeBool(d.hasCDL) === driverFilters.hasCDL) && + + (!driverFilters.cdlClass || + d.cdlClass?.toLowerCase().includes(driverFilters.cdlClass.toLowerCase())) && + + // (!driverFilters.ownerOperator || + // String(d.ownerOperator) === driverFilters.ownerOperator) && + + (!driverFilters.ownerOperator || + normalizeBool(d.ownerOperator) === driverFilters.ownerOperator) && + + // (!driverFilters.availableNow || + // String(d.availableNow) === driverFilters.availableNow)&& + + (!driverFilters.availableNow || + normalizeBool(d.availableNow) === driverFilters.availableNow) ); }); @@ -292,6 +626,32 @@ const AvailableTable: React.FC = () => { fetchDrivers(); }; + // const parseValue = (key: string, value: any, prev: any) => { + // const original = prev[key]; + + // if (typeof original === "number") return value === "" ? 0 : Number(value); + + // // if (typeof original === "boolean") return value === "true"; + // if (typeof original === "boolean") { + // if (value === "") return false; + // return value === "true"; + // } + // return value; + // }; + const parseValue = (key: string, value: any, prev: any) => { + const original = prev[key]; + + if (typeof original === "number") { + return value === "" ? 0 : Number(value); + } + + if (typeof original === "boolean") { + return value === "true" || value === true; + } + + return value; + }; + // ====================================================== // RENDER // ====================================================== @@ -422,8 +782,100 @@ const AvailableTable: React.FC = () => { setDriverFilters((p) => ({ ...p, search: e.target.value })) } /> + + setDriverFilters((p) => ({ + ...p, + company: e.target.value, + })) + } + /> + + + setDriverFilters((p) => ({ + ...p, + city: e.target.value, + })) + } + /> + + + setDriverFilters((p) => ({ + ...p, + state: e.target.value, + })) + } + /> + + + setDriverFilters((p) => ({ + ...p, + driverType: e.target.value, + })) + } + /> + + + setDriverFilters((p) => ({ + ...p, + vehicleType: e.target.value, + })) + } + /> + + + + + + + + {/* */} + -
{/* ====================================================== @@ -431,18 +883,44 @@ const AvailableTable: React.FC = () => { ====================================================== */}

All Loads

-
+ {/*
*/} + {loads.length === 0 ? ( +

No loads found

+ ) : ( +
+ )}

My Loads

-
+ {/*
*/} + {userLoads.length === 0 ? ( +

No loads found

+ ) : ( +
+ )} +

All Drivers

-
+ {/*
*/} + {drivers.length === 0 ? ( +

No drivers found

+ ) : ( + )}

My Drivers

-
+ {/*
*/} + {userDrivers.length === 0 ? ( +

No drivers found

+ ) : ( + + + + )} + {/* ====================================================== @@ -493,7 +971,6 @@ const AvailableTable: React.FC = () => { const userId = localStorage.getItem("userId"); console.log("USER ID:", userId); - // const payload = { // ...newLoad, @@ -727,11 +1204,14 @@ const AvailableTable: React.FC = () => { + value={ + (newLoad as any)[key] === undefined || (newLoad as any)[key] === null + ? "" + : String((newLoad as any)[key]) + } onChange={(e) => setNewLoad((p: any) => ({ ...p, - [key]: e.target.value, + [key]: parseValue(key, e.target.value, p), })) } /> @@ -765,30 +1245,87 @@ const AvailableTable: React.FC = () => { const userId = localStorage.getItem("userId"); - await axios.post(`${API_BASE}/api/drivers`, { + const payload = { ...newDriver, + userId, - }); - setNewDriver({ description: "", company: "" }); + yearsExperience: Number( + newDriver.yearsExperience || 0 + ), + + desiredPay: Number( + newDriver.desiredPay || 0 + ), + + completedJobs: Number( + newDriver.completedJobs || 0 + ), + + cancelledJobs: Number( + newDriver.cancelledJobs || 0 + ), + + noShows: Number( + newDriver.noShows || 0 + ), + + rating: Number( + newDriver.rating || 0 + ), + + truckYear: Number( + newDriver.truckYear || 0 + ), + + maxDistanceFromHome: Number( + newDriver.maxDistanceFromHome || 0 + ), + + availableDate: + normalizeDate( + newDriver.availableDate + ), + + medicalCardExpiration: + normalizeDate( + newDriver.medicalCardExpiration + ), + + licenseExpirationDate: + normalizeDate( + newDriver.licenseExpirationDate + ), + }; + + await axios.post( + `${API_BASE}/api/drivers`, + payload + ); + + setNewDriver(defaultDriver); refreshAll(); }} > - - setNewDriver((p) => ({ ...p, description: e.target.value })) - } - /> - - - setNewDriver((p) => ({ ...p, company: e.target.value })) - } - /> + {Object.keys(defaultDriver).map( + (key) => ( + + setNewDriver((p: any) => ({ + ...p, + [key]: parseValue(key, e.target.value, p), + })) + } + /> + ) + )}
+ + + {columns.map((column) => ( + + ))} + + + + + {data.map((driver, index) => ( + + {columns.map((column) => ( + + ))} + + ))} + +
{column}
+ {column === "userId" && + driver.userId ? ( + + View + + ) : ( + formatValue( + driver[column] + ) + )} +
+ + + ); +}; + +export default React.memo(DriversTable); \ No newline at end of file diff --git a/client/src/containers/User/AvailableTable/LoadTable.tsx b/client/src/containers/User/AvailableTable/LoadTable.tsx new file mode 100644 index 0000000..e69de29 diff --git a/controllers/DriverController.js b/controllers/DriverController.js index ccaa78b..ee51e17 100644 --- a/controllers/DriverController.js +++ b/controllers/DriverController.js @@ -1,50 +1,408 @@ // controllers/DriverController.js + const db = require("../models"); const driverController = { + // ===================================================== + // GET ALL DRIVERS + // ===================================================== getAllDrivers: async (req, res) => { try { - const allDrivers = await db.Driver.findAll(); + const allDrivers = await db.Driver.findAll({ + order: [["createdAt", "DESC"]], + }); + res.status(200).json(allDrivers); } catch (error) { console.error("Error fetching drivers:", error); - res.status(500).json({ error: "Failed to fetch drivers" }); + + res.status(500).json({ + error: "Failed to fetch drivers", + }); } }, + // ===================================================== + // CREATE DRIVER + // ===================================================== createDriver: async (req, res) => { - const { description, company, userId } = req.body; - try { - // Check if user exists + const { + // PROFILE + firstName, + lastName, + displayName, + profilePhoto, + description, + company, + archived, + status, + + // CONTACT + phoneNumber, + alternatePhone, + email, + preferredContactMethod, + website, + + // LOCATION + city, + state, + zipCode, + country, + currentLocationCity, + currentLocationState, + willingToRelocate, + willingToTravelNationwide, + + // DRIVER TYPE + driverType, + vehicleType, + availableNow, + + // LICENSE + hasCDL, + cdlClass, + licenseNumber, + licenseState, + licenseExpirationDate, + + // ENDORSEMENTS + hazmatEndorsement, + tankerEndorsement, + doublesTriplesEndorsement, + passengerEndorsement, + schoolBusEndorsement, + twicCard, + passportReady, + + // EXPERIENCE + yearsExperience, + accidentsLast3Years, + movingViolationsLast3Years, + duiHistory, + felonyHistory, + + // EQUIPMENT EXPERIENCE + dryVanExperience, + reeferExperience, + flatbedExperience, + stepDeckExperience, + rgnExperience, + hotshotExperience, + boxTruckExperience, + straightTruckExperience, + cargoVanExperience, + sprinterVanExperience, + + // EMPLOYMENT + employmentType, + desiredPay, + payType, + availableDate, + currentlyEmployed, + + // ROUTE PREFERENCES + prefersLocal, + prefersRegional, + prefersOTR, + preferredHomeTime, + preferredStates, + maxDistanceFromHome, + + // MEDICAL + medicalCardExpiration, + clearinghouseRegistered, + sapCompleted, + + // OWNER OPERATOR + ownerOperator, + ownsTruck, + truckYear, + truckMake, + truckModel, + truckType, + trailerType, + + // REPUTATION + rating, + completedJobs, + cancelledJobs, + noShows, + + // VERIFICATION + emailVerified, + phoneVerified, + identityVerified, + backgroundCheckVerified, + insuranceVerified, + + resumeDocument, + profileGallery, + licenseDocument, + medicalCardDocument, + insuranceDocument, + twicDocument, + passportDocument, + backgroundCheckDocument, + drugTestDocument, + motorVehicleRecordDocument, + employmentHistoryDocument, + additionalDocuments, + + emergencyContactName, + emergencyContactPhone, + emergencyContactRelationship, + + skills, + languages, + + forkliftCertified, + palletJackExperience, + liftGateExperience, + loadSecurementExperience, + oversizeLoadExperience, + + // SYSTEM + userId, + } = req.body; + + // ----------------------------------------- + // Verify User Exists + // ----------------------------------------- const userExists = await db.User.findByPk(userId); + if (!userExists) { - return res.status(400).json({ error: "User does not exist." }); + return res.status(400).json({ + error: "User does not exist.", + }); } - // Create the new driver + // ----------------------------------------- + // Create Driver + // ----------------------------------------- const newDriver = await db.Driver.create({ + // PROFILE + firstName, + lastName, + displayName, + profilePhoto, description, company, - userId, // Use the validated userId + archived, + status, + + // CONTACT + phoneNumber, + alternatePhone, + email, + preferredContactMethod, + website, + + // LOCATION + city, + state, + zipCode, + country, + currentLocationCity, + currentLocationState, + willingToRelocate, + willingToTravelNationwide, + + // DRIVER TYPE + driverType, + vehicleType, + availableNow, + + // LICENSE + hasCDL, + cdlClass, + licenseNumber, + licenseState, + licenseExpirationDate, + + // ENDORSEMENTS + hazmatEndorsement, + tankerEndorsement, + doublesTriplesEndorsement, + passengerEndorsement, + schoolBusEndorsement, + twicCard, + passportReady, + + // EXPERIENCE + yearsExperience, + accidentsLast3Years, + movingViolationsLast3Years, + duiHistory, + felonyHistory, + + // EQUIPMENT EXPERIENCE + dryVanExperience, + reeferExperience, + flatbedExperience, + stepDeckExperience, + rgnExperience, + hotshotExperience, + boxTruckExperience, + straightTruckExperience, + cargoVanExperience, + sprinterVanExperience, + + // EMPLOYMENT + employmentType, + desiredPay, + payType, + availableDate, + currentlyEmployed, + + // ROUTE PREFERENCES + prefersLocal, + prefersRegional, + prefersOTR, + preferredHomeTime, + preferredStates, + maxDistanceFromHome, + + // MEDICAL + medicalCardExpiration, + clearinghouseRegistered, + sapCompleted, + + // OWNER OPERATOR + ownerOperator, + ownsTruck, + truckYear, + truckMake, + truckModel, + truckType, + trailerType, + + // REPUTATION + rating, + completedJobs, + cancelledJobs, + noShows, + + // VERIFICATION + emailVerified, + phoneVerified, + identityVerified, + backgroundCheckVerified, + insuranceVerified, + + resumeDocument, + profileGallery, + licenseDocument, + medicalCardDocument, + insuranceDocument, + twicDocument, + passportDocument, + backgroundCheckDocument, + drugTestDocument, + motorVehicleRecordDocument, + employmentHistoryDocument, + additionalDocuments, + + emergencyContactName, + emergencyContactPhone, + emergencyContactRelationship, + + skills, + languages, + + forkliftCertified, + palletJackExperience, + liftGateExperience, + loadSecurementExperience, + oversizeLoadExperience, + + // SYSTEM + userId, }); + res.status(201).json(newDriver); } catch (error) { console.error("Error creating driver:", error); - res.status(500).json({ error: "Failed to create driver" }); + + res.status(500).json({ + error: "Failed to create driver", + details: error.message, + }); } }, + // ===================================================== + // GET DRIVERS FOR USER + // ===================================================== getAllUserDrivers: async (req, res) => { const { userId } = req.params; + try { const userDrivers = await db.Driver.findAll({ - where: { userId }, + where: { + userId, + }, + order: [["createdAt", "DESC"]], }); + res.status(200).json(userDrivers); } catch (error) { console.error("Error fetching user drivers:", error); - res.status(500).json({ error: "Failed to fetch user drivers" }); + + res.status(500).json({ + error: "Failed to fetch user drivers", + }); + } + }, + + // ===================================================== + // GET DRIVER BY ID + // ===================================================== + getDriverById: async (req, res) => { + try { + const driver = await db.Driver.findByPk(req.params.id); + + if (!driver) { + return res.status(404).json({ + error: "Driver not found", + }); + } + + res.status(200).json(driver); + } catch (error) { + console.error("Error fetching driver:", error); + + res.status(500).json({ + error: "Failed to fetch driver", + }); + } + }, + + // ===================================================== + // DELETE DRIVER + // ===================================================== + deleteDriver: async (req, res) => { + try { + const driver = await db.Driver.findByPk(req.params.id); + + if (!driver) { + return res.status(404).json({ + error: "Driver not found", + }); + } + + await driver.destroy(); + + res.status(200).json({ + message: "Driver deleted successfully", + }); + } catch (error) { + console.error("Error deleting driver:", error); + + res.status(500).json({ + error: "Failed to delete driver", + }); } }, }; diff --git a/models/driver.js b/models/driver.js index 239e3fb..0b8d150 100644 --- a/models/driver.js +++ b/models/driver.js @@ -1,33 +1,613 @@ module.exports = function (sequelize, DataTypes) { const Driver = sequelize.define("Driver", { - description: { + // ===================================================== + // PROFILE + // ===================================================== + + firstName: { type: DataTypes.STRING, allowNull: false, - defaultValue: "This is my first driver", + defaultValue: "", + }, + + lastName: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "", + }, + + displayName: { + type: DataTypes.STRING, + allowNull: true, + }, + + profilePhoto: { + type: DataTypes.TEXT, + allowNull: true, }, + + description: { + type: DataTypes.TEXT, + allowNull: true, + }, + + company: { + type: DataTypes.STRING, + allowNull: true, + }, + archived: { type: DataTypes.BOOLEAN, - allowNull: false, defaultValue: false, }, - company: { + + status: { + type: DataTypes.STRING, + defaultValue: "AVAILABLE", + }, + + // ===================================================== + // CONTACT + // ===================================================== + + phoneNumber: { + type: DataTypes.STRING, + allowNull: true, + }, + + alternatePhone: { + type: DataTypes.STRING, + allowNull: true, + }, + + email: { + type: DataTypes.STRING, + allowNull: true, + }, + + preferredContactMethod: { + type: DataTypes.STRING, + allowNull: true, + }, + + website: { + type: DataTypes.STRING, + allowNull: true, + }, + + // ===================================================== + // LOCATION + // ===================================================== + + city: { + type: DataTypes.STRING, + allowNull: true, + }, + + state: { + type: DataTypes.STRING, + allowNull: true, + }, + + zipCode: { + type: DataTypes.STRING, + allowNull: true, + }, + + country: { + type: DataTypes.STRING, + defaultValue: "USA", + }, + + currentLocationCity: { + type: DataTypes.STRING, + allowNull: true, + }, + + currentLocationState: { + type: DataTypes.STRING, + allowNull: true, + }, + + willingToRelocate: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + willingToTravelNationwide: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // DRIVER TYPE + // ===================================================== + + driverType: { + type: DataTypes.STRING, + defaultValue: "DELIVERY", + }, + + vehicleType: { + type: DataTypes.STRING, + allowNull: true, + }, + + availableNow: { + type: DataTypes.BOOLEAN, + defaultValue: true, + }, + + // ===================================================== + // LICENSE + // ===================================================== + + hasCDL: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + cdlClass: { + type: DataTypes.STRING, + allowNull: true, + }, + + licenseNumber: { + type: DataTypes.STRING, + allowNull: true, + }, + + licenseState: { + type: DataTypes.STRING, + allowNull: true, + }, + + licenseExpirationDate: { + type: DataTypes.DATE, + allowNull: true, + }, + + // ===================================================== + // ENDORSEMENTS + // ===================================================== + + hazmatEndorsement: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + tankerEndorsement: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + doublesTriplesEndorsement: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + passengerEndorsement: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + schoolBusEndorsement: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + twicCard: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + passportReady: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // EXPERIENCE + // ===================================================== + + yearsExperience: { + type: DataTypes.INTEGER, + defaultValue: 0, + }, + + accidentsLast3Years: { + type: DataTypes.INTEGER, + defaultValue: 0, + }, + + movingViolationsLast3Years: { + type: DataTypes.INTEGER, + defaultValue: 0, + }, + + duiHistory: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + felonyHistory: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // EQUIPMENT EXPERIENCE + // ===================================================== + + dryVanExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + reeferExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + flatbedExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + stepDeckExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + rgnExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + hotshotExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + boxTruckExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + straightTruckExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + cargoVanExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + sprinterVanExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // EMPLOYMENT + // ===================================================== + + employmentType: { + type: DataTypes.STRING, + allowNull: true, + }, + + desiredPay: { + type: DataTypes.DECIMAL(12, 2), + allowNull: true, + }, + + payType: { type: DataTypes.STRING, allowNull: true, }, + + availableDate: { + type: DataTypes.DATE, + allowNull: true, + }, + + currentlyEmployed: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // ROUTE PREFERENCES + // ===================================================== + + prefersLocal: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + prefersRegional: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + prefersOTR: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + preferredHomeTime: { + type: DataTypes.STRING, + allowNull: true, + }, + + preferredStates: { + type: DataTypes.TEXT, + allowNull: true, + }, + + maxDistanceFromHome: { + type: DataTypes.INTEGER, + allowNull: true, + }, + + // ===================================================== + // MEDICAL + // ===================================================== + + medicalCardExpiration: { + type: DataTypes.DATE, + allowNull: true, + }, + + clearinghouseRegistered: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + sapCompleted: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // OWNER OPERATOR + // ===================================================== + + ownerOperator: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + ownsTruck: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + truckYear: { + type: DataTypes.INTEGER, + allowNull: true, + }, + + truckMake: { + type: DataTypes.STRING, + allowNull: true, + }, + + truckModel: { + type: DataTypes.STRING, + allowNull: true, + }, + + truckType: { + type: DataTypes.STRING, + allowNull: true, + }, + + trailerType: { + type: DataTypes.STRING, + allowNull: true, + }, + + // ===================================================== + // REPUTATION + // ===================================================== + + rating: { + type: DataTypes.DECIMAL(3, 2), + defaultValue: 0, + }, + + completedJobs: { + type: DataTypes.INTEGER, + defaultValue: 0, + }, + + cancelledJobs: { + type: DataTypes.INTEGER, + defaultValue: 0, + }, + + noShows: { + type: DataTypes.INTEGER, + defaultValue: 0, + }, + + // ===================================================== + // VERIFICATION + // ===================================================== + + emailVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + phoneVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + identityVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + backgroundCheckVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + insuranceVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // DOCUMENTS + // ===================================================== + + resumeDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + profileGallery: { + type: DataTypes.TEXT, + allowNull: true, + }, + + licenseDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + medicalCardDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + insuranceDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + twicDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + passportDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + backgroundCheckDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + drugTestDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + motorVehicleRecordDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + employmentHistoryDocument: { + type: DataTypes.TEXT, + allowNull: true, + }, + + additionalDocuments: { + type: DataTypes.TEXT, + allowNull: true, + }, + + // ===================================================== + // EMERGENCY CONTACT + // ===================================================== + + emergencyContactName: { + type: DataTypes.STRING, + allowNull: true, + }, + + emergencyContactPhone: { + type: DataTypes.STRING, + allowNull: true, + }, + + emergencyContactRelationship: { + type: DataTypes.STRING, + allowNull: true, + }, + + // ===================================================== + // SKILLS + // ===================================================== + + skills: { + type: DataTypes.TEXT, + allowNull: true, + }, + + languages: { + type: DataTypes.TEXT, + allowNull: true, + }, + + // ===================================================== + // EQUIPMENT SKILLS + // ===================================================== + + forkliftCertified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + palletJackExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + liftGateExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + loadSecurementExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + oversizeLoadExperience: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + + // ===================================================== + // SYSTEM + // ===================================================== + userId: { - // Foreign key reference to User - type: DataTypes.INTEGER, // Assuming User ID is an integer + type: DataTypes.INTEGER, allowNull: false, references: { - model: "Users", // Correctly matches the table name for the User model - key: "id", // Matches the primary key of the User model + model: "Users", + key: "id", }, }, }); - // Associations Driver.associate = (models) => { - Driver.belongsTo(models.User, { foreignKey: "userId", as: "user" }); + Driver.belongsTo(models.User, { + foreignKey: "userId", + as: "user", + }); }; return Driver;