Merge pull request #182 from Oloodi/175-web-vendor-role-end-to-end-flow-integration
175 web vendor role end to end flow integration
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
mutation CreateStaff(
|
mutation CreateStaff(
|
||||||
$employeeName: String!,
|
$employeeName: String!,
|
||||||
$vendorId: UUID,
|
$vendorId: String,
|
||||||
$vendorName: String,
|
$vendorName: String,
|
||||||
$manager: String,
|
$manager: String,
|
||||||
$contactNumber: String,
|
$contactNumber: String,
|
||||||
@@ -10,12 +10,12 @@ mutation CreateStaff(
|
|||||||
$track: String,
|
$track: String,
|
||||||
$position: String,
|
$position: String,
|
||||||
$profileType: ProfileType,
|
$profileType: ProfileType,
|
||||||
$employmentType: EmploymentType!,
|
$employmentType: EmploymentType,
|
||||||
$english: EnglishLevel,
|
$english: EnglishLevel,
|
||||||
$rate: Float,
|
$rate: Float,
|
||||||
$rating: Float,
|
$rating: Float,
|
||||||
$reliabilityScore: Int,
|
$reliabilityScore: Int,
|
||||||
$backgroundCheckStatus: BackgroundCheckStatus!
|
$backgroundCheckStatus: BackgroundCheckStatus,
|
||||||
$notes: String
|
$notes: String
|
||||||
) @auth(level: USER) {
|
) @auth(level: USER) {
|
||||||
staff_insert(
|
staff_insert(
|
||||||
@@ -45,7 +45,7 @@ mutation CreateStaff(
|
|||||||
mutation UpdateStaff(
|
mutation UpdateStaff(
|
||||||
$id: UUID!,
|
$id: UUID!,
|
||||||
$employeeName: String,
|
$employeeName: String,
|
||||||
$vendorId: UUID,
|
$vendorId: String,
|
||||||
$vendorName: String,
|
$vendorName: String,
|
||||||
$manager: String,
|
$manager: String,
|
||||||
$contactNumber: String,
|
$contactNumber: String,
|
||||||
@@ -60,7 +60,7 @@ mutation UpdateStaff(
|
|||||||
$rate: Float,
|
$rate: Float,
|
||||||
$rating: Float,
|
$rating: Float,
|
||||||
$reliabilityScore: Int,
|
$reliabilityScore: Int,
|
||||||
$backgroundCheckStatus: BackgroundCheckStatus
|
$backgroundCheckStatus: BackgroundCheckStatus,
|
||||||
$notes: String
|
$notes: String
|
||||||
) @auth(level: USER) {
|
) @auth(level: USER) {
|
||||||
staff_update(
|
staff_update(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ query getStaffById(
|
|||||||
|
|
||||||
query filterStaff(
|
query filterStaff(
|
||||||
$employeeName: String,
|
$employeeName: String,
|
||||||
$vendorId: UUID,
|
$vendorId: String,
|
||||||
$department: StaffDepartment,
|
$department: StaffDepartment,
|
||||||
$employmentType: EmploymentType,
|
$employmentType: EmploymentType,
|
||||||
$english: EnglishLevel,
|
$english: EnglishLevel,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ enum BackgroundCheckStatus {
|
|||||||
type Staff @table(name: "staffs") {
|
type Staff @table(name: "staffs") {
|
||||||
id: UUID! @default(expr: "uuidV4()")
|
id: UUID! @default(expr: "uuidV4()")
|
||||||
employeeName: String! @col(name: "employee_name")
|
employeeName: String! @col(name: "employee_name")
|
||||||
vendorId: UUID @col(name: "vendor_id") # vendor_id (FK lógica a Vendor.id)
|
vendorId: String @col(name: "vendor_id") # vendor_id (FK lógica a Vendor.id)
|
||||||
vendorName: String @col(name: "vendor_name")
|
vendorName: String @col(name: "vendor_name")
|
||||||
manager: String
|
manager: String
|
||||||
contactNumber: String @col(name: "contact_number")
|
contactNumber: String @col(name: "contact_number")
|
||||||
@@ -53,12 +53,12 @@ type Staff @table(name: "staffs") {
|
|||||||
track: String
|
track: String
|
||||||
position: String
|
position: String
|
||||||
profileType: ProfileType @col(name: "profile_type")
|
profileType: ProfileType @col(name: "profile_type")
|
||||||
employmentType: EmploymentType! @col(name: "employment_type")
|
employmentType: EmploymentType @col(name: "employment_type")
|
||||||
english: EnglishLevel
|
english: EnglishLevel
|
||||||
rate: Float
|
rate: Float
|
||||||
rating: Float
|
rating: Float
|
||||||
reliabilityScore: Int @col(name: "reliability_score")
|
reliabilityScore: Int @col(name: "reliability_score")
|
||||||
backgroundCheckStatus: BackgroundCheckStatus! @col(name: "background_check_status")
|
backgroundCheckStatus: BackgroundCheckStatus @col(name: "background_check_status")
|
||||||
notes: String
|
notes: String
|
||||||
createdDate: Timestamp @default(expr: "request.time")
|
createdDate: Timestamp @default(expr: "request.time")
|
||||||
updatedDate: Timestamp @default(expr: "request.time")
|
updatedDate: Timestamp @default(expr: "request.time")
|
||||||
|
|||||||
@@ -358,6 +358,39 @@ const normalizeResultToArray = (res) => {
|
|||||||
// --- Entities Module ( Data Connect, without REST Base44) ---
|
// --- Entities Module ( Data Connect, without REST Base44) ---
|
||||||
const entitiesModule = {};
|
const entitiesModule = {};
|
||||||
|
|
||||||
|
// --- Helper to convert snake_case to camelCase recursively ---
|
||||||
|
const toCamel = (value) => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map(toCamel);
|
||||||
|
}
|
||||||
|
if (value && typeof value === "object") {
|
||||||
|
return Object.entries(value).reduce((acc, [key, val]) => {
|
||||||
|
const camelKey = key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
||||||
|
acc[camelKey] = toCamel(val);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Helper to convert camelCase to snake_case recursively ---
|
||||||
|
const toSnake = (value) => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map(toSnake);
|
||||||
|
}
|
||||||
|
if (value && typeof value === "object") {
|
||||||
|
return Object.entries(value).reduce((acc, [key, val]) => {
|
||||||
|
const snakeKey = key
|
||||||
|
.replace(/([A-Z])/g, "_$1")
|
||||||
|
.toLowerCase();
|
||||||
|
acc[snakeKey] = toSnake(val);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
||||||
entitiesModule[entityName] = {
|
entitiesModule[entityName] = {
|
||||||
|
|
||||||
@@ -378,101 +411,90 @@ Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//return fn(dataConnect);
|
let sort;
|
||||||
/*let variables;
|
let limit;
|
||||||
const maybeVars = params[0];
|
let baseVariables; // por si algún list usa variables (como Team)
|
||||||
|
|
||||||
if (maybeVars && typeof maybeVars === 'object' && !Array.isArray(maybeVars)) {
|
if (args.length === 1) {
|
||||||
variables = maybeVars;
|
const [a0] = args;
|
||||||
|
if (typeof a0 === "string") {
|
||||||
|
// list('-created_date')
|
||||||
|
sort = a0;
|
||||||
|
} else if (a0 && typeof a0 === "object" && !Array.isArray(a0)) {
|
||||||
|
// list({ ...vars }) -> reservado para queries que acepten variables
|
||||||
|
baseVariables = a0;
|
||||||
|
}
|
||||||
|
} else if (args.length === 2) {
|
||||||
|
const [a0, a1] = args;
|
||||||
|
if (typeof a0 === "string" && typeof a1 === "number") {
|
||||||
|
// list('-created_date', 50)
|
||||||
|
sort = a0;
|
||||||
|
limit = a1;
|
||||||
|
} else if (a0 && typeof a0 === "object" && !Array.isArray(a0)) {
|
||||||
|
// list({ ...vars }, '-created_date')
|
||||||
|
baseVariables = a0;
|
||||||
|
if (typeof a1 === "string") sort = a1;
|
||||||
|
}
|
||||||
|
} else if (args.length >= 3) {
|
||||||
|
const [a0, a1, a2] = args;
|
||||||
|
if (a0 && typeof a0 === "object" && !Array.isArray(a0)) {
|
||||||
|
// list({ ...vars }, '-created_date', 50)
|
||||||
|
baseVariables = a0;
|
||||||
|
if (typeof a1 === "string") sort = a1;
|
||||||
|
if (typeof a2 === "number") limit = a2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// COMMENT FIX: variables que realmente se mandan a DataConnect
|
||||||
|
let variables = baseVariables;
|
||||||
|
|
||||||
|
// COMMENT FIX: caso especial para Team, que SÍ tiene orderBy/limit en el query
|
||||||
|
if (entityName === "Team") {
|
||||||
|
variables = variables || {};
|
||||||
|
if (sort) {
|
||||||
|
const desc = sort.startsWith("-");
|
||||||
|
variables.orderByCreatedDate = desc ? "DESC" : "ASC";
|
||||||
|
}
|
||||||
|
if (typeof limit === "number") {
|
||||||
|
variables.limit = limit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await fn(dataConnect, variables);
|
const res = await fn(dataConnect, variables);
|
||||||
return normalizeResultToArray(res);
|
let items = normalizeResultToArray(res);
|
||||||
*/
|
|
||||||
|
|
||||||
let sort;
|
// COMMENT FIX: para entidades que NO tienen orderBy/limit en el query,
|
||||||
let limit;
|
// aplicamos sort/limit en el front como fallback.
|
||||||
let baseVariables; // por si algún list usa variables (como Team)
|
if (entityName !== "Team" && sort) {
|
||||||
|
const desc = sort.startsWith("-");
|
||||||
|
const field = desc ? sort.slice(1) : sort; // '-created_date' -> 'created_date'
|
||||||
|
|
||||||
if (args.length === 1) {
|
items = items.slice().sort((a, b) => {
|
||||||
const [a0] = args;
|
const av = a?.[field];
|
||||||
if (typeof a0 === "string") {
|
const bv = b?.[field];
|
||||||
// list('-created_date')
|
|
||||||
sort = a0;
|
|
||||||
} else if (a0 && typeof a0 === "object" && !Array.isArray(a0)) {
|
|
||||||
// list({ ...vars }) -> reservado para queries que acepten variables
|
|
||||||
baseVariables = a0;
|
|
||||||
}
|
|
||||||
} else if (args.length === 2) {
|
|
||||||
const [a0, a1] = args;
|
|
||||||
if (typeof a0 === "string" && typeof a1 === "number") {
|
|
||||||
// list('-created_date', 50)
|
|
||||||
sort = a0;
|
|
||||||
limit = a1;
|
|
||||||
} else if (a0 && typeof a0 === "object" && !Array.isArray(a0)) {
|
|
||||||
// list({ ...vars }, '-created_date')
|
|
||||||
baseVariables = a0;
|
|
||||||
if (typeof a1 === "string") sort = a1;
|
|
||||||
}
|
|
||||||
} else if (args.length >= 3) {
|
|
||||||
const [a0, a1, a2] = args;
|
|
||||||
if (a0 && typeof a0 === "object" && !Array.isArray(a0)) {
|
|
||||||
// list({ ...vars }, '-created_date', 50)
|
|
||||||
baseVariables = a0;
|
|
||||||
if (typeof a1 === "string") sort = a1;
|
|
||||||
if (typeof a2 === "number") limit = a2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// COMMENT FIX: variables que realmente se mandan a DataConnect
|
if (av == null && bv == null) return 0;
|
||||||
let variables = baseVariables;
|
if (av == null) return 1;
|
||||||
|
if (bv == null) return -1;
|
||||||
|
|
||||||
// COMMENT FIX: caso especial para Team, que SÍ tiene orderBy/limit en el query
|
const da = new Date(av);
|
||||||
if (entityName === "Team") {
|
const db = new Date(bv);
|
||||||
variables = variables || {};
|
if (!isNaN(da) && !isNaN(db)) {
|
||||||
if (sort) {
|
return desc ? db - da : da - db;
|
||||||
const desc = sort.startsWith("-");
|
}
|
||||||
variables.orderByCreatedDate = desc ? "DESC" : "ASC";
|
|
||||||
}
|
|
||||||
if (typeof limit === "number") {
|
|
||||||
variables.limit = limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await fn(dataConnect, variables);
|
if (av < bv) return desc ? 1 : -1;
|
||||||
let items = normalizeResultToArray(res);
|
if (av > bv) return desc ? -1 : 1;
|
||||||
|
return 0;
|
||||||
// COMMENT FIX: para entidades que NO tienen orderBy/limit en el query,
|
});
|
||||||
// aplicamos sort/limit en el front como fallback.
|
|
||||||
if (entityName !== "Team" && sort) {
|
|
||||||
const desc = sort.startsWith("-");
|
|
||||||
const field = desc ? sort.slice(1) : sort; // '-created_date' -> 'created_date'
|
|
||||||
|
|
||||||
items = items.slice().sort((a, b) => {
|
|
||||||
const av = a?.[field];
|
|
||||||
const bv = b?.[field];
|
|
||||||
|
|
||||||
if (av == null && bv == null) return 0;
|
|
||||||
if (av == null) return 1;
|
|
||||||
if (bv == null) return -1;
|
|
||||||
|
|
||||||
const da = new Date(av);
|
|
||||||
const db = new Date(bv);
|
|
||||||
if (!isNaN(da) && !isNaN(db)) {
|
|
||||||
return desc ? db - da : da - db;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av < bv) return desc ? 1 : -1;
|
if (entityName !== "Team" && typeof limit === "number") {
|
||||||
if (av > bv) return desc ? -1 : 1;
|
items = items.slice(0, limit);
|
||||||
return 0;
|
}
|
||||||
});
|
//console.log(items)
|
||||||
}
|
//return items;
|
||||||
|
return items.map(toSnake);
|
||||||
if (entityName !== "Team" && typeof limit === "number") {
|
|
||||||
items = items.slice(0, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -486,14 +508,6 @@ Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*const { data } = params ?? {};
|
|
||||||
if (!data) {
|
|
||||||
throw new Error(
|
|
||||||
`${entityName}.create expects a payload like { data: { ...fields } }`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn(dataConnect, data);*/
|
|
||||||
if (!params || typeof params !== 'object') {
|
if (!params || typeof params !== 'object') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`${entityName}.create expects an object with the fields to insert`
|
`${entityName}.create expects an object with the fields to insert`
|
||||||
@@ -510,6 +524,9 @@ Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
|||||||
payload = params;
|
payload = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//converting to camelCase for data connect
|
||||||
|
payload = toCamel(payload);
|
||||||
|
|
||||||
return fn(dataConnect, payload);
|
return fn(dataConnect, payload);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -528,13 +545,16 @@ Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
|||||||
throw new Error(`${entityName}.get expects an object of variables (e.g. { id })`);
|
throw new Error(`${entityName}.get expects an object of variables (e.g. { id })`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fn(dataConnect, params);
|
//return fn(dataConnect, params);
|
||||||
|
const result = await fn(dataConnect, params);
|
||||||
|
return toSnake(result);
|
||||||
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
//update
|
//update
|
||||||
...(ops.update && {
|
...(ops.update && {
|
||||||
update: async (params) => {
|
update: async (id,params) => {
|
||||||
const fn = dcSdk[ops.update];
|
const fn = dcSdk[ops.update];
|
||||||
if (typeof fn !== 'function') {
|
if (typeof fn !== 'function') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -548,7 +568,8 @@ Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id, data } = params;
|
//const { id, data } = params;
|
||||||
|
let data = params;
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new Error(`${entityName}.update requires an "id" field`);
|
throw new Error(`${entityName}.update requires an "id" field`);
|
||||||
@@ -560,6 +581,9 @@ Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data && typeof data === "object") {
|
||||||
|
data = toCamel(data);
|
||||||
|
}
|
||||||
const vars = { id, ...data };
|
const vars = { id, ...data };
|
||||||
|
|
||||||
return fn(dataConnect, vars);
|
return fn(dataConnect, vars);
|
||||||
|
|||||||
@@ -14,35 +14,35 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
employee_name: "",
|
employee_name: "",
|
||||||
manager: "",
|
manager: "",
|
||||||
contact_number: "",
|
contact_number: "",
|
||||||
phone: "",
|
//phone: "",
|
||||||
email: "", // Added email field
|
email: "", // Added email field
|
||||||
department: "",
|
department: "",
|
||||||
hub_location: "",
|
hub_location: "",
|
||||||
event_location: "",
|
//event_location: "",
|
||||||
track: "",
|
track: "",
|
||||||
address: "",
|
//address: "",
|
||||||
city: "",
|
//city: "",
|
||||||
position: "",
|
position: "",
|
||||||
position_2: "",
|
//position_2: "",
|
||||||
initial: "",
|
//initial: "",
|
||||||
profile_type: "",
|
profile_type: "",
|
||||||
employment_type: "",
|
employment_type: "",
|
||||||
english: "",
|
english: "",
|
||||||
english_required: false,
|
//english_required: false,
|
||||||
check_in: "",
|
//check_in: "",
|
||||||
replaced_by: "",
|
//replaced_by: "",
|
||||||
ro: "",
|
//ro: "",
|
||||||
mon: "",
|
//mon: "",
|
||||||
schedule_days: "",
|
//schedule_days: "",
|
||||||
invoiced: false,
|
//invoiced: false,
|
||||||
action: "",
|
//action: "",
|
||||||
notes: "",
|
notes: "",
|
||||||
accounting_comments: "",
|
//accounting_comments: "",
|
||||||
rating: 0,
|
rating: 0,
|
||||||
shift_coverage_percentage: 100,
|
//shift_coverage_percentage: 100,
|
||||||
cancellation_count: 0,
|
//cancellation_count: 0,
|
||||||
no_show_count: 0, // Added no_show_count field
|
//no_show_count: 0, // Added no_show_count field
|
||||||
total_shifts: 0,
|
//total_shifts: 0,
|
||||||
reliability_score: 100
|
reliability_score: 100
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="initial" className="text-slate-700 font-medium">Initials</Label>
|
<Label htmlFor="initial" className="text-slate-700 font-medium">Initials</Label>
|
||||||
<Input
|
<Input
|
||||||
id="initial"
|
id="initial"
|
||||||
@@ -90,7 +90,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
maxLength={3}
|
maxLength={3}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="position" className="text-slate-700 font-medium">Primary Skill</Label>
|
<Label htmlFor="position" className="text-slate-700 font-medium">Primary Skill</Label>
|
||||||
@@ -103,7 +103,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="position_2" className="text-slate-700 font-medium">Secondary Skill</Label>
|
<Label htmlFor="position_2" className="text-slate-700 font-medium">Secondary Skill</Label>
|
||||||
<Input
|
<Input
|
||||||
id="position_2"
|
id="position_2"
|
||||||
@@ -112,7 +112,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
placeholder="e.g., Dishwasher, Prep Cook"
|
placeholder="e.g., Dishwasher, Prep Cook"
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="profile_type" className="text-slate-700 font-medium">Skill Level</Label>
|
<Label htmlFor="profile_type" className="text-slate-700 font-medium">Skill Level</Label>
|
||||||
@@ -121,9 +121,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
<SelectValue placeholder="Select skill level" />
|
<SelectValue placeholder="Select skill level" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="Skilled">Skilled</SelectItem>
|
<SelectItem value="SKILLED">Skilled</SelectItem>
|
||||||
<SelectItem value="Beginner">Beginner</SelectItem>
|
<SelectItem value="BEGINNER">Beginner</SelectItem>
|
||||||
<SelectItem value="Cross-Trained">Cross-Trained</SelectItem>
|
<SelectItem value="CROSS_TRAINED">Cross-Trained</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@@ -135,13 +135,13 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
<SelectValue placeholder="Select type" />
|
<SelectValue placeholder="Select type" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="Full Time">Full Time</SelectItem>
|
<SelectItem value="FULL_TIME">Full Time</SelectItem>
|
||||||
<SelectItem value="Part Time">Part Time</SelectItem>
|
<SelectItem value="PART_TIME">Part Time</SelectItem>
|
||||||
<SelectItem value="On call">On call</SelectItem>
|
<SelectItem value="ON_CALL">On call</SelectItem>
|
||||||
<SelectItem value="Weekends">Weekends</SelectItem>
|
<SelectItem value="WEEKENDS">Weekends</SelectItem>
|
||||||
<SelectItem value="Specific Days">Specific Days</SelectItem>
|
<SelectItem value="SPECIFIC_DAYS">Specific Days</SelectItem>
|
||||||
<SelectItem value="Seasonal">Seasonal</SelectItem>
|
<SelectItem value="SEASONAL">Seasonal</SelectItem>
|
||||||
<SelectItem value="Medical Leave">Medical Leave</SelectItem>
|
<SelectItem value="MEDICAL_LEAVE">Medical Leave</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@@ -187,7 +187,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="phone" className="text-slate-700 font-medium">Additional Phone</Label>
|
<Label htmlFor="phone" className="text-slate-700 font-medium">Additional Phone</Label>
|
||||||
<Input
|
<Input
|
||||||
id="phone"
|
id="phone"
|
||||||
@@ -196,7 +196,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('phone', e.target.value)}
|
onChange={(e) => handleChange('phone', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -234,7 +234,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="shift_coverage_percentage" className="text-slate-700 font-medium">Shift Coverage %</Label>
|
<Label htmlFor="shift_coverage_percentage" className="text-slate-700 font-medium">Shift Coverage %</Label>
|
||||||
<Input
|
<Input
|
||||||
id="shift_coverage_percentage"
|
id="shift_coverage_percentage"
|
||||||
@@ -245,9 +245,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('shift_coverage_percentage', parseInt(e.target.value) || 0)}
|
onChange={(e) => handleChange('shift_coverage_percentage', parseInt(e.target.value) || 0)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="cancellation_count" className="text-slate-700 font-medium">Cancellation Count</Label>
|
<Label htmlFor="cancellation_count" className="text-slate-700 font-medium">Cancellation Count</Label>
|
||||||
<Input
|
<Input
|
||||||
id="cancellation_count"
|
id="cancellation_count"
|
||||||
@@ -257,10 +257,10 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('cancellation_count', parseInt(e.target.value) || 0)}
|
onChange={(e) => handleChange('cancellation_count', parseInt(e.target.value) || 0)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
{/* New No Show Count field */}
|
{/* New No Show Count field */}
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="no_show_count" className="text-slate-700 font-medium">No Show Count</Label>
|
<Label htmlFor="no_show_count" className="text-slate-700 font-medium">No Show Count</Label>
|
||||||
<Input
|
<Input
|
||||||
id="no_show_count"
|
id="no_show_count"
|
||||||
@@ -270,10 +270,10 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('no_show_count', parseInt(e.target.value) || 0)}
|
onChange={(e) => handleChange('no_show_count', parseInt(e.target.value) || 0)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
{/* End new No Show Count field */}
|
{/* End new No Show Count field */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="total_shifts" className="text-slate-700 font-medium">Total Shifts</Label>
|
<Label htmlFor="total_shifts" className="text-slate-700 font-medium">Total Shifts</Label>
|
||||||
<Input
|
<Input
|
||||||
id="total_shifts"
|
id="total_shifts"
|
||||||
@@ -283,9 +283,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('total_shifts', parseInt(e.target.value) || 0)}
|
onChange={(e) => handleChange('total_shifts', parseInt(e.target.value) || 0)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2 flex items-end">
|
{/* <div className="space-y-2 flex items-end">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="invoiced"
|
id="invoiced"
|
||||||
@@ -296,7 +296,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
Invoiced
|
Invoiced
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -314,19 +314,19 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
<SelectValue placeholder="Select department" />
|
<SelectValue placeholder="Select department" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="Operations">Operations</SelectItem>
|
<SelectItem value="OPERATIONS">Operations</SelectItem>
|
||||||
<SelectItem value="Sales">Sales</SelectItem>
|
<SelectItem value="SALES">Sales</SelectItem>
|
||||||
<SelectItem value="HR">HR</SelectItem>
|
<SelectItem value="HR">HR</SelectItem>
|
||||||
<SelectItem value="Finance">Finance</SelectItem>
|
<SelectItem value="FINANCE">Finance</SelectItem>
|
||||||
<SelectItem value="IT">IT</SelectItem>
|
<SelectItem value="IT">IT</SelectItem>
|
||||||
<SelectItem value="Marketing">Marketing</SelectItem>
|
<SelectItem value="MARKETING">Marketing</SelectItem>
|
||||||
<SelectItem value="Customer Service">Customer Service</SelectItem>
|
<SelectItem value="CUSTOMER_SERVICE">Customer Service</SelectItem>
|
||||||
<SelectItem value="Logistics">Logistics</SelectItem>
|
<SelectItem value="LOGISTICS">Logistics</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="city" className="text-slate-700 font-medium">City</Label>
|
<Label htmlFor="city" className="text-slate-700 font-medium">City</Label>
|
||||||
<Input
|
<Input
|
||||||
id="city"
|
id="city"
|
||||||
@@ -335,7 +335,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
placeholder="e.g., San Francisco"
|
placeholder="e.g., San Francisco"
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="hub_location" className="text-slate-700 font-medium">Hub Location</Label>
|
<Label htmlFor="hub_location" className="text-slate-700 font-medium">Hub Location</Label>
|
||||||
@@ -347,7 +347,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="event_location" className="text-slate-700 font-medium">Event Location</Label>
|
<Label htmlFor="event_location" className="text-slate-700 font-medium">Event Location</Label>
|
||||||
<Input
|
<Input
|
||||||
id="event_location"
|
id="event_location"
|
||||||
@@ -355,7 +355,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('event_location', e.target.value)}
|
onChange={(e) => handleChange('event_location', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="track" className="text-slate-700 font-medium">Track</Label>
|
<Label htmlFor="track" className="text-slate-700 font-medium">Track</Label>
|
||||||
@@ -367,7 +367,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2 md:col-span-2">
|
{/* <div className="space-y-2 md:col-span-2">
|
||||||
<Label htmlFor="address" className="text-slate-700 font-medium">Address</Label>
|
<Label htmlFor="address" className="text-slate-700 font-medium">Address</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
id="address"
|
id="address"
|
||||||
@@ -376,7 +376,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
rows={2}
|
rows={2}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -394,15 +394,15 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
<SelectValue placeholder="Select level" />
|
<SelectValue placeholder="Select level" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="Fluent">Fluent</SelectItem>
|
<SelectItem value="FLUENT">Fluent</SelectItem>
|
||||||
<SelectItem value="Intermediate">Intermediate</SelectItem>
|
<SelectItem value="INTERMEDIATE">Intermediate</SelectItem>
|
||||||
<SelectItem value="Basic">Basic</SelectItem>
|
<SelectItem value="BASIC">Basic</SelectItem>
|
||||||
<SelectItem value="None">None</SelectItem>
|
<SelectItem value="NONE">None</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2 flex items-end">
|
{/* <div className="space-y-2 flex items-end">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="english_required"
|
id="english_required"
|
||||||
@@ -413,9 +413,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
English Required
|
English Required
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="check_in" className="text-slate-700 font-medium">Last Check-in</Label>
|
<Label htmlFor="check_in" className="text-slate-700 font-medium">Last Check-in</Label>
|
||||||
<Input
|
<Input
|
||||||
id="check_in"
|
id="check_in"
|
||||||
@@ -424,9 +424,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('check_in', e.target.value)}
|
onChange={(e) => handleChange('check_in', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="schedule_days" className="text-slate-700 font-medium">Schedule Days</Label>
|
<Label htmlFor="schedule_days" className="text-slate-700 font-medium">Schedule Days</Label>
|
||||||
<Input
|
<Input
|
||||||
id="schedule_days"
|
id="schedule_days"
|
||||||
@@ -435,7 +435,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
placeholder="e.g., Mon-Fri, 9AM-5PM"
|
placeholder="e.g., Mon-Fri, 9AM-5PM"
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -446,7 +446,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-6">
|
<CardContent className="p-6">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="replaced_by" className="text-slate-700 font-medium">Replaced By</Label>
|
<Label htmlFor="replaced_by" className="text-slate-700 font-medium">Replaced By</Label>
|
||||||
<Input
|
<Input
|
||||||
id="replaced_by"
|
id="replaced_by"
|
||||||
@@ -454,9 +454,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('replaced_by', e.target.value)}
|
onChange={(e) => handleChange('replaced_by', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="action" className="text-slate-700 font-medium">Action</Label>
|
<Label htmlFor="action" className="text-slate-700 font-medium">Action</Label>
|
||||||
<Input
|
<Input
|
||||||
id="action"
|
id="action"
|
||||||
@@ -464,9 +464,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('action', e.target.value)}
|
onChange={(e) => handleChange('action', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="ro" className="text-slate-700 font-medium">R.O</Label>
|
<Label htmlFor="ro" className="text-slate-700 font-medium">R.O</Label>
|
||||||
<Input
|
<Input
|
||||||
id="ro"
|
id="ro"
|
||||||
@@ -474,9 +474,9 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('ro', e.target.value)}
|
onChange={(e) => handleChange('ro', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2">
|
{/* <div className="space-y-2">
|
||||||
<Label htmlFor="mon" className="text-slate-700 font-medium">MON</Label>
|
<Label htmlFor="mon" className="text-slate-700 font-medium">MON</Label>
|
||||||
<Input
|
<Input
|
||||||
id="mon"
|
id="mon"
|
||||||
@@ -484,7 +484,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
onChange={(e) => handleChange('mon', e.target.value)}
|
onChange={(e) => handleChange('mon', e.target.value)}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="space-y-2 md:col-span-2">
|
<div className="space-y-2 md:col-span-2">
|
||||||
<Label htmlFor="notes" className="text-slate-700 font-medium">Notes</Label>
|
<Label htmlFor="notes" className="text-slate-700 font-medium">Notes</Label>
|
||||||
@@ -497,7 +497,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2 md:col-span-2">
|
{/* <div className="space-y-2 md:col-span-2">
|
||||||
<Label htmlFor="accounting_comments" className="text-slate-700 font-medium">Accounting Comments</Label>
|
<Label htmlFor="accounting_comments" className="text-slate-700 font-medium">Accounting Comments</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
id="accounting_comments"
|
id="accounting_comments"
|
||||||
@@ -506,7 +506,7 @@ export default function StaffForm({ staff, onSubmit, isSubmitting }) {
|
|||||||
rows={3}
|
rows={3}
|
||||||
className="border-slate-200"
|
className="border-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ export default function EditStaff() {
|
|||||||
queryClient.invalidateQueries({ queryKey: ['staff'] });
|
queryClient.invalidateQueries({ queryKey: ['staff'] });
|
||||||
navigate(createPageUrl("Dashboard"));
|
navigate(createPageUrl("Dashboard"));
|
||||||
},
|
},
|
||||||
|
onError: (error, variables) => {
|
||||||
|
console.log("data: ",variables);
|
||||||
|
console.error("Update failed", error);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmit = (staffData) => {
|
const handleSubmit = (staffData) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user