- Add /api/portal/team.cfm for employee listing - Add chat endpoints (getMessages, sendMessage, markRead, getActiveChat) - Add OTP authentication endpoints - Add address management endpoints (delete, setDefault, states) - Add task completion and chat task endpoints - Update Application.cfm allowlist Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
93 lines
2.7 KiB
Text
93 lines
2.7 KiB
Text
<cfsetting showdebugoutput="false">
|
|
<cfsetting enablecfoutputonly="true">
|
|
<cfcontent type="application/json; charset=utf-8" reset="true">
|
|
|
|
<cfscript>
|
|
// Search users by phone, email, or username
|
|
// Input: Query (search term)
|
|
// Output: { OK: true, USERS: [...] }
|
|
|
|
function apiAbort(required struct payload) {
|
|
writeOutput(serializeJSON(payload));
|
|
abort;
|
|
}
|
|
|
|
function readJsonBody() {
|
|
var raw = getHttpRequestData().content;
|
|
if (isNull(raw)) raw = "";
|
|
if (!len(trim(raw))) return {};
|
|
try {
|
|
var data = deserializeJSON(raw);
|
|
if (isStruct(data)) return data;
|
|
} catch (any e) {}
|
|
return {};
|
|
}
|
|
|
|
try {
|
|
data = readJsonBody();
|
|
query = structKeyExists(data, "Query") ? trim(data.Query) : "";
|
|
currentUserId = val(structKeyExists(data, "CurrentUserID") ? data.CurrentUserID : 0);
|
|
|
|
if (len(query) < 3) {
|
|
apiAbort({ "OK": true, "USERS": [], "MESSAGE": "Query must be at least 3 characters" });
|
|
}
|
|
|
|
// Search by phone, email, or first/last name
|
|
// Exclude the current user from results
|
|
searchTerm = "%" & query & "%";
|
|
|
|
qUsers = queryExecute("
|
|
SELECT
|
|
u.UserID,
|
|
u.UserFirstName,
|
|
u.UserLastName,
|
|
u.UserEmail,
|
|
u.UserPhone,
|
|
u.UserAvatarPath
|
|
FROM Users u
|
|
WHERE u.UserID != :currentUserId
|
|
AND (
|
|
u.UserPhone LIKE :searchTerm
|
|
OR u.UserEmail LIKE :searchTerm
|
|
OR u.UserFirstName LIKE :searchTerm
|
|
OR u.UserLastName LIKE :searchTerm
|
|
OR CONCAT(u.UserFirstName, ' ', u.UserLastName) LIKE :searchTerm
|
|
)
|
|
ORDER BY u.UserFirstName, u.UserLastName
|
|
LIMIT 10
|
|
", {
|
|
currentUserId: { value: currentUserId, cfsqltype: "cf_sql_integer" },
|
|
searchTerm: { value: searchTerm, cfsqltype: "cf_sql_varchar" }
|
|
}, { datasource: "payfrit" });
|
|
|
|
users = [];
|
|
for (user in qUsers) {
|
|
// Mask phone number for privacy (show last 4 digits only)
|
|
maskedPhone = "";
|
|
if (len(trim(user.UserPhone)) >= 4) {
|
|
maskedPhone = "***-***-" & right(user.UserPhone, 4);
|
|
}
|
|
|
|
arrayAppend(users, {
|
|
"UserID": user.UserID,
|
|
"Name": trim(user.UserFirstName & " " & user.UserLastName),
|
|
"Email": user.UserEmail,
|
|
"Phone": maskedPhone,
|
|
"AvatarUrl": len(trim(user.UserAvatarPath)) ? "https://biz.payfrit.com/uploads/" & user.UserAvatarPath : ""
|
|
});
|
|
}
|
|
|
|
apiAbort({
|
|
"OK": true,
|
|
"USERS": users,
|
|
"COUNT": arrayLen(users)
|
|
});
|
|
|
|
} catch (any e) {
|
|
apiAbort({
|
|
"OK": false,
|
|
"ERROR": "server_error",
|
|
"MESSAGE": e.message
|
|
});
|
|
}
|
|
</cfscript>
|