diff --git a/src/components/vendor.tsx b/src/components/vendor.tsx index afad35a..4643d84 100644 --- a/src/components/vendor.tsx +++ b/src/components/vendor.tsx @@ -1,4 +1,5 @@ import { FC, Fragment, ReactNode } from 'react'; +import { Distance } from '../elements/distance'; import { Hyperlink } from '../elements/hyperlink'; import { Tag } from '../elements/tag'; import { Icon, IconName } from '../identity/icon'; @@ -52,6 +53,8 @@ const styles = { offer: 'font-sans break-word mt-2 mb-8 flex-grow-0', region: 'font-sans text-gray-500 fill-current text-base font-light tracking-tight inline-flex flex-row items-center mb-4', regionIcon: 'mr-2 flex-shrink-0', + distance: + 'font-sans text-gray-500 fill-current text-base font-light tracking-tight inline-flex flex-row items-center mb-4', tags: 'my-2 flex flex-wrap', col: 'flex flex-col lg:flex-row w-full box-border', @@ -76,9 +79,23 @@ type Props = { hours: string[]; options: string[]; contact: string[]; + coordinates?: number[]; + userCoordinates?: number[]; }; -export const Vendor: FC = ({ title, tags, region, body, categories, hours, address, options, contact }) => ( +export const Vendor: FC = ({ + title, + tags, + region, + body, + categories, + hours, + address, + options, + contact, + coordinates, + userCoordinates, +}) => (
  • {/* = ({ title, tags, region, body, categories, hours {region} + {coordinates && userCoordinates && ( +
    + +
    + )} + {address && (
    Ort diff --git a/src/compositions/search-with-results.tsx b/src/compositions/search-with-results.tsx index e7211c3..6e10558 100644 --- a/src/compositions/search-with-results.tsx +++ b/src/compositions/search-with-results.tsx @@ -29,6 +29,9 @@ const getVendors = `query Vendors($service: [Service!], $zip: Int, $tenants: [Te address order contact + location { + coordinates + } } total }`; @@ -45,7 +48,7 @@ export const SearchWithResults: FC = ({ query, categories }) => { const [zip, setZip] = useState(''); const [categoryFilter, setCategoryFilter] = useState([]); - const [, postcode] = useGetCurrentPosition(); + const [userCoordinates, postcode] = useGetCurrentPosition(); useEffect(() => { if (query['zip']) { @@ -91,7 +94,7 @@ export const SearchWithResults: FC = ({ query, categories }) => { const { vendors } = data; - return vendors.map(({ name, id, categories, contact, hours, address, body, order, region, service }) => ( + return vendors.map(({ name, id, categories, contact, hours, address, body, order, region, service, location }) => ( = ({ query, categories }) => { address={address} options={order} contact={contact} + coordinates={location && location.coordinates} + userCoordinates={userCoordinates} /> )); }, diff --git a/src/compositions/vendor-list.tsx b/src/compositions/vendor-list.tsx index c9b2211..3022805 100644 --- a/src/compositions/vendor-list.tsx +++ b/src/compositions/vendor-list.tsx @@ -4,12 +4,13 @@ import { Vendor as VendorType } from '../entities/vendor'; type Props = { vendors: VendorType[]; + userCoordinates?: number[]; }; -export const VendorList: FC = ({ vendors }) => { +export const VendorList: FC = ({ vendors, userCoordinates }) => { return (
      - {vendors.map(({ name, id, categories, contact, hours, address, body, order, region, service }) => ( + {vendors.map(({ name, id, categories, contact, hours, address, body, order, region, service, location }) => ( = ({ vendors }) => { address={address} options={order} contact={contact} + coordinates={location && location.coordinates} + userCoordinates={userCoordinates} /> ))}
    diff --git a/src/elements/distance.tsx b/src/elements/distance.tsx new file mode 100644 index 0000000..52de5c1 --- /dev/null +++ b/src/elements/distance.tsx @@ -0,0 +1,37 @@ +import { FC, ReactNode } from 'react'; + +const getDistance = (userLat: number, userLon: number, vendorLat: number, vendorLon: number) => { + if (userLat == vendorLat && userLon == vendorLon) { + return 0; + } else { + const radlat1 = (Math.PI * userLat) / 180; + const radlat2 = (Math.PI * vendorLat) / 180; + const theta = userLon - vendorLon; + const radtheta = (Math.PI * theta) / 180; + const distance = + ((Math.acos( + Math.min(1, Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta)) + ) * + 180) / + Math.PI) * + 60 * + 1.1515 * + 1.609344; + + if (distance < 2) { + return 'in der Nähe'; + } + + if (distance > 100) { + return 'über 100km entfernt'; + } + + return `${Math.round(distance)}km entfernt`; + } +}; + +type Props = { className?: string; userLat: number; userLon: number; vendorLat: number; vendorLon: number }; + +export const Distance: FC = ({ userLat, userLon, vendorLat, vendorLon, className = '' }) => ( + {getDistance(userLat, userLon, vendorLat, vendorLon)} +); diff --git a/src/entities/vendor.ts b/src/entities/vendor.ts index f666da3..30261bc 100644 --- a/src/entities/vendor.ts +++ b/src/entities/vendor.ts @@ -15,14 +15,16 @@ type VendorData = { order: Order[]; contact: string[]; tenant: Tenant; + location?: Location; +}; + +type Location = { + type: 'Point'; + coordinates: [number, number]; }; export type MongoVendor = { _id: string; - location?: { - type: 'Point'; - coordinates: [number, number]; - }; } & VendorData; export type Vendor = { diff --git a/src/schemas/graphql.ts b/src/schemas/graphql.ts index 62f763f..8cc9ad6 100644 --- a/src/schemas/graphql.ts +++ b/src/schemas/graphql.ts @@ -38,6 +38,11 @@ export const schema = buildSchema(` SFY } + type Location { + type: String! + coordinates: [Float!]! + } + type Vendor { id: String! name: String! @@ -50,6 +55,7 @@ export const schema = buildSchema(` order: [Order]! contact: [String]! tenant: String! + location: Location } input VendorInput {