Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions screens/AttendanceAction.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function AttendanceAction() {
const [distanceInfo, setDistanceInfo] = useState(null);
const [actionLoading, setActionLoading] = useState(false);
const [restrictLocation, setRestrictLocation] = useState("0");
const [unrestrictedCheckout, setUnrestrictedCheckout] = useState("0");
const [restrictionLoaded, setRestrictionLoaded] = useState(false);
const [onBreak, setOnBreak] = useState(false);
const [liveBreakTime, setLiveBreakTime] = useState("00:00:00");
Expand Down Expand Up @@ -125,8 +126,10 @@ function AttendanceAction() {
useEffect(() => {
const loadRestriction = async () => {
const r = await AsyncStorage.getItem("restrict_location");
const u = await AsyncStorage.getItem("unrestricted_checkout_location");
if (!isMountedRef.current) return;
setRestrictLocation(r === "1" ? "1" : "0");
setUnrestrictedCheckout(u === "1" ? "1" : "0");
setRestrictionLoaded(true);
};
loadRestriction();
Expand Down Expand Up @@ -745,7 +748,9 @@ function AttendanceAction() {
</SafeAreaView>
);
}

const allowCheckoutAnywhere =
checkin === true && unrestrictedCheckout === "1";

Comment on lines +751 to +753
Comment on lines +751 to +753
return (
<SafeAreaView
style={{ flex: 1, backgroundColor: "white" }}
Expand Down Expand Up @@ -941,9 +946,18 @@ function AttendanceAction() {
<TouchableOpacity
className={`justify-center items-center h-16 w-full mt-4 rounded-2xl ${
checkin ? "bg-red-600" : "bg-green-600"
} ${restrictLocation === "1" && !inTarget ? "opacity-50" : ""}`}
} ${
restrictLocation === "1" &&
!inTarget &&
!allowCheckoutAnywhere
? "opacity-50"
: ""
}`}
disabled={
actionLoading || (restrictLocation === "1" && !inTarget)
actionLoading ||
(restrictLocation === "1" &&
!inTarget &&
!allowCheckoutAnywhere)
Comment on lines +949 to +960
Comment on lines +949 to +960
}
onPress={async () => {
try {
Expand Down
9 changes: 8 additions & 1 deletion screens/AttendanceCamera.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,16 @@ function AttendanceCamera() {
await AsyncStorage.getItem("restrict_location")
)?.trim();

const unrestrictedCheckout = (
await AsyncStorage.getItem("unrestricted_checkout_location")
)?.trim();

const shouldSkipLocationRestriction =
type === "OUT" && unrestrictedCheckout === "1";

// 📍 Only call location API if restriction is enabled
let locationData = null;
if (restrictLocation === "1") {
if (!shouldSkipLocationRestriction && restrictLocation === "1") {
locationData = await getOfficeLocation(employeeCode);

// If not within radius, block
Expand Down
24 changes: 18 additions & 6 deletions screens/QrScan.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ function QrScan() {
"Employee_Code",
"Full_Name",
"Photo",
"Restrict Location", // :point_left: NEW FIELD
"Restrict Location",
"Unrestricted Checkout Location",
"User_id",
"API",
"App_key",
Expand All @@ -60,8 +61,8 @@ function QrScan() {
value = value
.replace(/[\u0000-\u001F\u00A0]+/g, " ")
.replace(
/[%#;]+(?:\s+)?(Company|Employee_Code|Full_Name|Photo|Restrict Location|User_id|API|App_key)(?:\s*[:=])/g,
(_, key) => `${key}:`
/[%#;]+(?:\s+)?(Company|Employee_Code|Full_Name|Photo|Restrict Location|Unrestricted Checkout Location|User_id|API|App_key)(?:\s*[:=])/g,
(_, key) => `${key}:`,
)
.replace(/[^\S\r\n]+/g, " ")
.trim();
Expand All @@ -70,7 +71,7 @@ function QrScan() {
const keyAlt = KEYS.join("|");
const pairRE = new RegExp(
`\\b(${keyAlt})\\s*[:=]\\s*([\\s\\S]*?)(?=\\s*(?:${keyAlt})\\s*[:=]|$)`,
"gi"
"gi",
);
let m;
while ((m = pairRE.exec(value))) {
Expand Down Expand Up @@ -106,7 +107,13 @@ function QrScan() {
app_key: appKey,
photo: photoFlag,
restrict_location: qrData["Restrict Location"]?.trim() ?? "0", // :point_left: NEW
unrestricted_checkout_location:
qrData["Unrestricted Checkout Location"]?.trim() ?? "0",
};
console.log(
"QR UNRESTRICTED VALUE:",
cleanedData.unrestricted_checkout_location,
);
Comment on lines +113 to +116
Comment on lines +113 to +116
// :eight: Validate required fields
if (
cleanedData.company &&
Expand All @@ -122,6 +129,10 @@ function QrScan() {
["baseUrl", cleanedData.baseUrl],
["photo", String(cleanedData.photo)],
["restrict_location", cleanedData.restrict_location], // :point_left: NEW
[
"unrestricted_checkout_location",
cleanedData.unrestricted_checkout_location,
],
]);
// Redux dispatch (NO restrict_location)
dispatch(setUsername(cleanedData.api_key));
Expand Down Expand Up @@ -151,7 +162,7 @@ function QrScan() {
if (result?.canceled) return;
if (result.assets[0]?.uri) {
const scannedResults = await Camera.scanFromURLAsync(
result.assets[0].uri
result.assets[0].uri,
);
const { data } = scannedResults[0];
await handleQRCodeData(data);
Expand All @@ -174,6 +185,7 @@ function QrScan() {
</SafeAreaView>
);
}

return (
<CameraView
barcodeScannerSettings={{ barcodeTypes: ["qr"] }}
Expand Down Expand Up @@ -234,4 +246,4 @@ function QrScan() {
</CameraView>
);
}
export default QrScan;
export default QrScan;
14 changes: 13 additions & 1 deletion services/api/attendance.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,23 @@ export const userCheckIn = async ({ employeeCode, type, locationData }) => {
const restrictLocation = (
await AsyncStorage.getItem("restrict_location")
)?.trim();

const unrestrictedCheckout = (
await AsyncStorage.getItem("unrestricted_checkout_location")
)?.trim();

let nearest = null;
let radius = null;

// 📍 Location restriction is enabled
if (restrictLocation && restrictLocation.toString() === "1") {
const shouldSkipLocationRestriction =
type === "OUT" && unrestrictedCheckout === "1";

if (
!shouldSkipLocationRestriction &&
restrictLocation &&
restrictLocation.toString() === "1"
) {
Comment on lines +202 to +217
nearest = await getOfficeLocation(employeeCode); // Returns closest office + distance

if (!nearest) {
Expand Down