Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: beckn/beckn-ui-workspace
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: beckn/beckn-ui-workspace
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: revert-1768-feature-448
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
Loading
Showing 3,146 changed files with 109,616 additions and 73,993 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ node_modules
.next
out
.env
coverage

# Swap the comments on the following lines if you don't wish to use zero-installs
# Documentation here: https://yarnpkg.com/features/zero-installs
4 changes: 4 additions & 0 deletions .vscode/project.code-workspace
Original file line number Diff line number Diff line change
@@ -8,6 +8,10 @@
"name": "Molecules",
"path": "../packages/molecules"
},
{
"name": "Common",
"path": "../packages/common"
},
{
"name": "Prettier",
"path": "../packages/prettier-config"
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -37,4 +37,6 @@ This monorepo is globally configured with the following tools and libraries:

6. **Commit-lint**: Enforces a structured commit message format. Please refer to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) documentation for commit message conventions.

Feel free to explore and contribute to the various front-end use-cases and BAPs within this monorepo. If you have any questions or need further assistance, please refer to the individual project documentation or reach out to the repository maintainers. Happy coding!
Feel free to explore and contribute to the various front-end use cases and BAPs within this monorepo. If you have any questions or need any more help, please refer to the individual project documentation or reach out to the repository maintainers.

Happy coding!
File renamed without changes.
File renamed without changes.
46 changes: 46 additions & 0 deletions apps/OSC/components/BottomModal/BottomModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useState } from 'react'
import { Transition } from '@headlessui/react'
import { AiOutlineClose } from 'react-icons/ai'
import { useLanguage } from '../../hooks/useLanguage'
import { Image } from '@chakra-ui/react'

interface ModalProps {
isOpen: boolean
onClose: () => void
children: React.ReactNode
partialClose?: boolean
}

const Modal: React.FC<ModalProps> = ({ isOpen, onClose, children, partialClose }) => {
const { t } = useLanguage()
return (
<Transition
show={isOpen}
onClick={() => onClose()}
>
<div className="fixed z-[9999] inset-0 flex items-end justify-center sm:p-0 bg-[#80808066] ">
<Transition.Child
unmount={false}
enter="transition-transform duration-300"
enterFrom="translate-y-full"
enterTo="translate-y-0"
leave="transition-transform duration-300"
leaveFrom="translate-y-0"
leaveTo="translate-y-full"
style={{ width: '100vw' }}
>
<div className="w-full px-4 pb-4 pt-2 mx-auto bg-[#fff] rounded-t-[1rem] shadow-lg sm:rounded-lg sm:overflow-hidden">
<Image
src="/images/Indicator.svg"
className="mx-auto mb-3"
alt="indicator"
/>
{children}
</div>
</Transition.Child>
</div>
</Transition>
)
}

export default Modal
56 changes: 56 additions & 0 deletions apps/OSC/components/BottomModal/BottomModalScan.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react'
import { Image, ModalOverlay, Modal, ModalContent, Box, ModalHeader, Divider, Flex } from '@chakra-ui/react'

interface ModalProps {
isOpen: boolean
onClose: () => void
children: React.ReactNode
partialClose?: boolean
modalHeader?: string
}

const BottomModal: React.FC<ModalProps> = ({ isOpen, onClose, children, modalHeader }) => {
return (
<>
<Modal
isCentered
onClose={onClose}
isOpen={isOpen}
scrollBehavior="outside"
motionPreset="slideInBottom"
>
<ModalOverlay height="100vh" />
<ModalContent
position="fixed"
bottom="0px"
pb="20px"
borderRadius="1rem 1rem 0px 0px"
maxW="lg"
>
<Flex
alignItems={'center'}
justifyContent={'space-between'}
padding={'20px 24px'}
>
<ModalHeader
textAlign="left"
fontSize="17px"
fontWeight={'600'}
p={'unset'}
flex={'unset'}
>
{modalHeader}
</ModalHeader>
<Box onClick={onClose}>
<Image src="/images/crossIcon.svg" />
</Box>
</Flex>
<Divider mb={'20px'} />
{children}
</ModalContent>
</Modal>
</>
)
}

export default BottomModal
File renamed without changes.
File renamed without changes
145 changes: 145 additions & 0 deletions apps/OSC/components/Map/Map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { MapContainer, TileLayer, Marker, Popup, useMap, ZoomControl } from 'react-leaflet'
import { Image } from '@chakra-ui/react'
import React, { useEffect, useState } from 'react'
import Control from 'react-leaflet-custom-control'
import 'leaflet/dist/leaflet.css'
import Icon from './store-marker.svg'
import SelectedIcon from './SelectedMarker.svg'
import CenterMarker from './CenterMarker.svg'
import L from 'leaflet'
import { isEmpty } from 'lodash'
import { getUserLocation } from '../../utilities/common-utils'

interface MapProps {
coords: { lat: number; long: number }
handleModalOpen: () => void
handleOptionDetailOpen: () => void
setSelectedStore: React.Dispatch<React.SetStateAction<any>>
selectedStore: any
// Using any for now since exact structure is not clear
stores: any[]
}

const Map: React.FC<MapProps> = ({
stores,
selectedStore,
coords,
handleModalOpen,
handleOptionDetailOpen,
setSelectedStore
}) => {
const { lat, long } = coords
const [userLocation, setUserLocation] = useState<[number, number] | null>(null)
const [flyToUserLocation, setFlyToUserLocation] = useState(false)

useEffect(() => {
getUserLocation()
.then(position => {
setUserLocation([position.coords.latitude, position.coords.longitude])
})
.catch(error => {
console.error(`Error getting user location: ${error.message}`)
})
}, [])

// Custom hook to zoom the map to the user's location
const ZoomToUserLocation = () => {
let map = useMap()

if (userLocation && flyToUserLocation) {
map.flyTo(userLocation, 12)
}

return null
}

const customIcon = new L.Icon({
iconUrl: Icon,
iconSize: [25, 35],
iconAnchor: [5, 30]
})

const customCenterMarker = new L.Icon({
iconUrl: CenterMarker,
iconSize: [40, 50],
iconAnchor: [5, 30]
})

const customSelectedIcon = new L.Icon({
iconUrl: Icon,
iconSize: [35, 45],
iconAnchor: [5, 30]
})

function MapView() {
let map = useMap()
map.setView([lat, long], map.getZoom())
return null
}

return (
<MapContainer
style={{ maxHeight: '100vh', height: '90vh' }}
center={[lat, long]}
zoom={16}
zoomControl={false}
scrollWheelZoom={true}
zoomAnimation={true}
>
<TileLayer
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>
contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Control
prepend
position="topright"
>
<div className="flex flex-col basis-4">
<Image
className="translate-x-0.5"
onClick={() => setFlyToUserLocation(true)}
src="/images/LocateMe.svg"
alt="..."
/>
</div>
</Control>

{!isEmpty(stores) &&
stores.map((item: any, index: number) => {
const isSelected = item.lat === selectedStore?.lat && item.lon === selectedStore?.lon
const IconToUse = isSelected ? customSelectedIcon : customIcon
return (
<Marker
icon={IconToUse}
key={item.lon}
position={[item.lat, item.lon]}
eventHandlers={{
click: () => {
setSelectedStore(item)
handleOptionDetailOpen()
}
}}
></Marker>
)
})}
<Marker
icon={customCenterMarker}
position={[lat, long]}
></Marker>
<ZoomControl position="topright" />

<MapView />
<ZoomToUserLocation />
</MapContainer>
)
}

// React memo not working for some reason
//TODO Needed because the map is re-rendered even if the co-ords are same causing a flickering issue on the map. Will fix this later
export default React.memo(Map, (prevProps, nextProps) => {
if (prevProps.coords.lat === nextProps.coords.lat && prevProps.coords.long === nextProps.coords.long) {
return true
}
return false
})
119 changes: 119 additions & 0 deletions apps/OSC/components/Map/MapSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { useState, useEffect } from 'react'
import { Spinner } from '@chakra-ui/react'
import { GoSearch } from 'react-icons/go'
import { isEmpty } from 'lodash'
import { Image } from '@chakra-ui/react'
import { useLanguage } from '../../hooks/useLanguage'
import useDebounce from '../../hooks/useDebounce'
import { Location } from '../../lib/types/search'
interface LocalNameFormat {
primaryName: string
secondaryName: string
}

function formatLocationName(name: string): LocalNameFormat {
const index = name.indexOf(',')
if (index !== -1) {
return {
primaryName: name.slice(0, index).trim(),
secondaryName: name.slice(index + 1).trim()
}
} else {
return {
primaryName: name.trim(),
secondaryName: ''
}
}
}

export interface SearchBarProp {
setQuery: React.Dispatch<React.SetStateAction<string>>
locations: Location[]
query: string
handleLocationClick: (lat: number, long: number) => void
fetchResults: (query: string) => void
setShowSuggestions: React.Dispatch<React.SetStateAction<boolean>>
}

const SearchBar: React.FC<SearchBarProp> = ({
setQuery,
locations,
query,
handleLocationClick,
fetchResults,
setShowSuggestions
}) => {
const { t } = useLanguage()
//TODO Pseudo loading for now. Need to figure out to do this using map load events
const [loading, setLoading] = useState<boolean>(false)

const [value, setValue] = useState<string>('')

const debouncedValue = useDebounce(value, 300)

useEffect(() => {
setShowSuggestions(!isEmpty(value) && locations && !isEmpty(locations))
}, [locations, value])

useEffect(() => {
setLoading(true)
setTimeout(() => {
setLoading(false)
}, 500)
}, [debouncedValue])

useEffect(() => {
// setQuery(debouncedValue);
fetchResults(debouncedValue)
}, [debouncedValue])

return (
<>
<div className="max-w-[50rem] w-[90%] md:w-[90%] px-4 mx-auto mt-4 mb-3 border border-[#C9C9C9] border-solid md:ltr:ml-4 md:rtl:mr-4 rounded-[12px] dark:bg-slate-800 flex items-center justify-center flex-grow search-location">
<GoSearch style={{ color: 'rgb(156 163 175)' }} />
<input
className="px-4 py-2 md:py-3 bg-transparent outline-none w-full text-[15px]"
type="search"
placeholder={`${t.search}`}
onChange={e => setValue(e.target.value)}
/>
{loading && (
<Spinner
color="#A71B4A"
size="sm"
/>
)}
</div>
{!isEmpty(value) && locations && !isEmpty(locations) && (
<div className="flex flex-col overflow-scroll max-h-[100vh] bg-white rounded-md h-[100vh] relative z-[9995] divide-y suggestion-list">
{locations.map(singleLocation => {
const { primaryName, secondaryName } = formatLocationName(singleLocation.display_name)
return (
<div
key={singleLocation.place_id}
className="text-ellipsis flex items-start gap-3 my-1 p-2 "
onClick={() => {
handleLocationClick(singleLocation.lat, singleLocation.lon)
setQuery(primaryName)
setValue('')
}}
>
<Image
className="mt-1"
src="/images/searchlocationmarker.svg"
alt="Location point"
/>
<div>
<h3 className="text-[15px]/[22.5px] font-[600] text-[#37474F]">{primaryName}</h3>
<h4 className="text-[15px]/[17.5px] font-[400] text-[#7C7C7C]">{secondaryName}</h4>
</div>
</div>
)
})}
</div>
)}
</>
)
}

export default SearchBar
Loading