Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3. Shared helpers in api/helpers.php (DB, auth, request/response, security). PDO prepared statements throughout. Same JSON response shapes as CFML.
102 lines
4.3 KiB
PHP
102 lines
4.3 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../helpers.php';
|
|
runAuth();
|
|
|
|
try {
|
|
$data = readJsonBody();
|
|
|
|
$token = trim($data['token'] ?? ($_GET['token'] ?? ''));
|
|
if ($token === '') {
|
|
apiAbort(['OK' => false, 'ERROR' => 'missing_token', 'MESSAGE' => 'Rating token is required.']);
|
|
}
|
|
|
|
$qRating = queryOne("
|
|
SELECT r.*, t.Title,
|
|
u_for.FirstName AS ForFirstName, u_for.LastName AS ForLastName,
|
|
u_by.FirstName AS ByFirstName, u_by.LastName AS ByLastName
|
|
FROM TaskRatings r
|
|
JOIN Tasks t ON t.ID = r.TaskID
|
|
LEFT JOIN Users u_for ON u_for.ID = r.ForUserID
|
|
LEFT JOIN Users u_by ON u_by.ID = r.ByUserID
|
|
WHERE r.AccessToken = ? LIMIT 1
|
|
", [$token]);
|
|
|
|
if (!$qRating) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'invalid_token', 'MESSAGE' => 'Rating not found or link is invalid.']);
|
|
}
|
|
|
|
if (strtotime($qRating['ExpiresOn']) < time()) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'expired', 'MESSAGE' => 'This rating link has expired.']);
|
|
}
|
|
|
|
if (!empty($qRating['CompletedOn'])) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'already_submitted', 'MESSAGE' => 'This rating has already been submitted.']);
|
|
}
|
|
|
|
// Check if this is a submission or info request
|
|
$isSubmission = isset($data['onTime']) || isset($data['completedScope'])
|
|
|| isset($data['requiredFollowup']) || isset($data['continueAllow'])
|
|
|| isset($data['prepared']) || isset($data['respectful'])
|
|
|| isset($data['wouldAutoAssign']);
|
|
|
|
if (!$isSubmission) {
|
|
$result = [
|
|
'OK' => true,
|
|
'RatingID' => (int) $qRating['ID'],
|
|
'Direction' => $qRating['Direction'],
|
|
'Title' => $qRating['Title'],
|
|
'ForUserName' => trim($qRating['ForFirstName'] . ' ' . $qRating['ForLastName']),
|
|
'ExpiresOn' => toISO8601($qRating['ExpiresOn']),
|
|
];
|
|
|
|
if ($qRating['Direction'] === 'customer_rates_worker' || $qRating['Direction'] === 'admin_rates_worker') {
|
|
$result['Questions'] = [
|
|
'onTime' => 'Was the worker on time?',
|
|
'completedScope' => 'Was the scope completed?',
|
|
'requiredFollowup' => 'Was follow-up required?',
|
|
'continueAllow' => 'Continue to allow these tasks?',
|
|
];
|
|
} elseif ($qRating['Direction'] === 'worker_rates_customer') {
|
|
$result['Questions'] = [
|
|
'prepared' => 'Was the customer prepared?',
|
|
'completedScope' => 'Was the scope clear?',
|
|
'respectful' => 'Was the customer respectful?',
|
|
'wouldAutoAssign' => 'Would you serve this customer again?',
|
|
];
|
|
}
|
|
|
|
jsonResponse($result);
|
|
}
|
|
|
|
// Process submission
|
|
$ratingId = (int) $qRating['ID'];
|
|
|
|
if ($qRating['Direction'] === 'customer_rates_worker' || $qRating['Direction'] === 'admin_rates_worker') {
|
|
queryTimed("
|
|
UPDATE TaskRatings SET OnTime = ?, CompletedScope = ?, RequiredFollowup = ?, ContinueAllow = ?, CompletedOn = NOW()
|
|
WHERE ID = ?
|
|
", [
|
|
isset($data['onTime']) ? ($data['onTime'] ? 1 : 0) : null,
|
|
isset($data['completedScope']) ? ($data['completedScope'] ? 1 : 0) : null,
|
|
isset($data['requiredFollowup']) ? ($data['requiredFollowup'] ? 1 : 0) : null,
|
|
isset($data['continueAllow']) ? ($data['continueAllow'] ? 1 : 0) : null,
|
|
$ratingId,
|
|
]);
|
|
} elseif ($qRating['Direction'] === 'worker_rates_customer') {
|
|
queryTimed("
|
|
UPDATE TaskRatings SET Prepared = ?, CompletedScope = ?, Respectful = ?, WouldAutoAssign = ?, CompletedOn = NOW()
|
|
WHERE ID = ?
|
|
", [
|
|
isset($data['prepared']) ? ($data['prepared'] ? 1 : 0) : null,
|
|
isset($data['completedScope']) ? ($data['completedScope'] ? 1 : 0) : null,
|
|
isset($data['respectful']) ? ($data['respectful'] ? 1 : 0) : null,
|
|
isset($data['wouldAutoAssign']) ? ($data['wouldAutoAssign'] ? 1 : 0) : null,
|
|
$ratingId,
|
|
]);
|
|
}
|
|
|
|
jsonResponse(['OK' => true, 'MESSAGE' => 'Rating submitted successfully. Thank you for your feedback!']);
|
|
|
|
} catch (Exception $e) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => 'Error submitting rating', 'DETAIL' => $e->getMessage()]);
|
|
}
|