Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/google maps link #10003

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1962,6 +1962,7 @@
"show_all_notifications": "Show All",
"show_all_slots": "Show all slots",
"show_default_presets": "Show Default Presets",
"show_on_maps": "Show On Maps",
"show_patient_presets": "Show Patient Presets",
"show_unread_notifications": "Show Unread",
"showing_all_appointments": "Showing all appointments",
Expand Down
10 changes: 10 additions & 0 deletions src/Utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ function _isAppleDevice() {
*/
export const isAppleDevice = _isAppleDevice();

/**
* Referred from: https://stackoverflow.com/questions/6031412/detect-android-phone-via-javascript-jquery
* @returns `true` if device is Android, else `false`
*/
function _isAndroidDevice(): boolean {
return /android/i.test(navigator.userAgent);
}

export const isAndroidDevice = _isAndroidDevice();
Comment on lines +96 to +104
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using more robust device detection methods.

The current implementation has several potential issues:

  1. User agent sniffing is unreliable as it can be spoofed.
  2. The constant is computed at module load time, which might not work in SSR environments.

Consider these alternatives:

  1. Use feature detection:
-function _isAndroidDevice(): boolean {
-  return /android/i.test(navigator.userAgent);
-}
-
-export const isAndroidDevice = _isAndroidDevice();
+export function isAndroidDevice(): boolean {
+  if (typeof window === 'undefined') return false;
+  
+  // Check if the platform-specific features are available
+  return (
+    'onorientationchange' in window &&
+    'ontouchstart' in window &&
+    navigator.maxTouchPoints > 0 &&
+    !('standalone' in navigator)
+  );
+}
  1. Or use modern APIs:
export function isAndroidDevice(): boolean {
  if (typeof window === 'undefined') return false;
  
  return navigator.userAgentData?.platform === 'Android';
}


/**
* Conditionally concatenate classes. An alternate replacement for `clsx`.
*
Expand Down
43 changes: 39 additions & 4 deletions src/components/Facility/FacilityHome.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import careConfig from "@careConfig";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { Hospital, MapPin, MoreVertical, Settings } from "lucide-react";
import {
Hospital,
MapPin,
MoreVertical,
Settings,
SquareArrowOutUpRight,
} from "lucide-react";
import { navigate } from "raviger";
import { useState } from "react";
import { useTranslation } from "react-i18next";
Expand Down Expand Up @@ -32,6 +38,7 @@ import request from "@/Utils/request/request";
import uploadFile from "@/Utils/request/uploadFile";
import { getAuthorizationHeader } from "@/Utils/request/utils";
import { sleep } from "@/Utils/utils";
import { isAndroidDevice } from "@/Utils/utils";
import EditFacilitySheet from "@/pages/Organization/components/EditFacilitySheet";
import { FacilityData } from "@/types/facility/facility";
import type {
Expand Down Expand Up @@ -88,6 +95,7 @@ const renderGeoOrganizations = (geoOrg: Organization) => {
};

export const FacilityHome = ({ facilityId }: Props) => {
console.log(navigator.platform);
const { t } = useTranslation();
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
const [editCoverImage, setEditCoverImage] = useState(false);
Expand All @@ -99,11 +107,9 @@ export const FacilityHome = ({ facilityId }: Props) => {
pathParams: { id: facilityId },
}),
});

const handleDeleteClose = () => {
setOpenDeleteDialog(false);
};

const handleDeleteSubmit = async () => {
await request(routes.deleteFacility, {
pathParams: { id: facilityId },
Expand All @@ -117,6 +123,29 @@ export const FacilityHome = ({ facilityId }: Props) => {
},
});
};
const getMapsLink = (latitude: number, longitude: number) => {
return isAndroidDevice ? (
<a
className="text-sm text-primary flex items-center gap-1 w-max"
href={`geo:0,0?q=${latitude},${longitude}`}
target="_blank"
rel="noreferrer"
>
{t("show_on_maps")}
<SquareArrowOutUpRight className="h-3 w-3" />
</a>
) : (
<a
className="text-sm text-primary flex items-center gap-1 w-max"
href={`https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`}
target="_blank"
rel="noreferrer"
>
{t("show_on_maps")}
<SquareArrowOutUpRight className="h-3 w-3" />
</a>
);
};

const handleCoverImageUpload = async (file: File, onError: () => void) => {
const formData = new FormData();
Expand Down Expand Up @@ -298,12 +327,18 @@ export const FacilityHome = ({ facilityId }: Props) => {
<MapPin className="mt-2 h-5 w-5 flex-shrink-0 text-muted-foreground" />
<div>
{facilityData?.geo_organization && (
<div className="mt-2 text-sm">
<div className="mt-1 text-sm">
{renderGeoOrganizations(
facilityData?.geo_organization,
)}
</div>
)}
{facilityData.latitude &&
facilityData.longitude &&
getMapsLink(
facilityData.latitude,
facilityData.longitude,
)}
</div>
</div>

Expand Down
Loading