├── .dockerignore ├── .eslintrc.yml ├── .github └── workflows │ └── docker-image.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── AcikKaynakPR.md ├── CONTRIBUTING.md ├── Dockerfile ├── README.md ├── README_ENG.md ├── dosya-aciklamalari.md ├── i18n.js ├── nginx.conf ├── package-lock.json ├── package.json ├── pages ├── _app.js ├── _document.js └── index.js ├── public ├── icons │ ├── Lock.svg │ ├── afet-harita.svg │ ├── afet-harita.webp │ ├── deprem-io.svg │ ├── deprem-io.webp │ ├── deprem-yardim.svg │ ├── deprem-yardim.webp │ ├── deprem_io.svg │ ├── filter-icon.svg │ ├── fullscreen.png │ ├── fullscreen.svg │ ├── hospital-1.png │ ├── hospital-1.svg │ ├── hospital-marker-2.png │ ├── hospital-marker-2.svg │ ├── hospital-marker.png │ ├── hospital-marker.svg │ ├── hospital.png │ ├── hospital.svg │ ├── left-icon.svg │ ├── lockOpen.svg │ ├── logo.svg │ ├── pharmacy-marker-2.png │ ├── pharmacy-marker-2.svg │ ├── pharmacy-marker.png │ ├── pharmacy-marker.svg │ ├── pill.png │ ├── pill.svg │ ├── plus.svg │ ├── search-icon.svg │ ├── show-all-icon.svg │ ├── vet copy.png │ ├── vet copy.svg │ ├── vet-marker.png │ ├── vet-marker.svg │ ├── vet.png │ └── vet.svg ├── images │ ├── header-bg-desktop.jpg │ ├── header-bg-mobile.jpg │ ├── logo.png │ └── logo.svg ├── index.html ├── locales │ ├── en │ │ └── common.json │ └── tr │ │ └── common.json ├── robots.txt └── sitemap.xml ├── src ├── App.js ├── components │ ├── DragIcon │ │ ├── DragIcon.js │ │ └── DragIcon.module.scss │ ├── Footer │ │ ├── Footer.js │ │ └── Footer.module.scss │ ├── FullScreenIcon │ │ └── FullScreenIcon.js │ ├── Header │ │ ├── Header │ │ │ ├── Header.js │ │ │ └── Header.module.scss │ │ ├── HeaderCombined.js │ │ ├── HeaderCombined.module.scss │ │ ├── HeaderRow.js │ │ ├── HeaderRow.module.scss │ │ ├── SearchBar.js │ │ └── SearchBar.module.scss │ ├── InfoCard │ │ ├── InfoCard.js │ │ └── InfoCard.module.scss │ ├── ListPage │ │ ├── ListPage.js │ │ └── ListPage.module.scss │ ├── MainViewContainer │ │ └── MainViewContainer.module.scss │ ├── MapMarkerCluster │ │ ├── MapMarkerCluster.js │ │ └── MapMarkerCluster.module.scss │ ├── MapPage │ │ ├── MapPage.js │ │ └── MapPage.module.scss │ └── Others │ │ ├── Others.js │ │ └── Others.module.scss ├── icons │ ├── afet-harita.svg │ ├── afet-harita.webp │ ├── deprem-io.svg │ ├── deprem-io.webp │ ├── deprem-yardim.svg │ ├── deprem-yardim.webp │ ├── deprem_io.svg │ ├── hospital-1.png │ ├── hospital-1.svg │ ├── hospital-marker-2.png │ ├── hospital-marker-2.svg │ ├── hospital-marker.png │ ├── hospital-marker.svg │ ├── logo.svg │ ├── pharmacy-marker-2.png │ ├── pharmacy-marker-2.svg │ ├── pharmacy-marker.png │ ├── pharmacy-marker.svg │ ├── vet-marker.png │ ├── vet-marker.svg │ ├── vet.png │ └── vet.svg ├── index.css ├── index.js ├── lib │ ├── Block │ │ ├── Block.js │ │ └── Block.module.scss │ ├── Icons.js │ ├── Spacer.js │ ├── city.js │ ├── cityCenters.js │ └── typeDataContext.js ├── styles │ ├── App.scss │ └── Homepage.scss └── utils │ ├── calculateCenter.js │ ├── constants.js │ ├── debounce.js │ ├── generalFunctions.js │ ├── hooks.js │ └── styled.js └── task-definition.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | build/ -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | es2021: true 4 | extends: 5 | - eslint:recommended 6 | - plugin:react/recommended 7 | - plugin:prettier/recommended 8 | - plugin:react-hooks/recommended 9 | overrides: [] 10 | parser: "@babel/eslint-parser" 11 | parserOptions: 12 | requireConfigFile: false 13 | ecmaVersion: latest 14 | sourceType: module 15 | babelOptions: 16 | presets: 17 | - "@babel/preset-react" 18 | plugins: 19 | - react 20 | - react-hooks 21 | rules: 22 | linebreak-style: 23 | - error 24 | - unix 25 | quotes: 26 | - error 27 | - double 28 | semi: 29 | - error 30 | - always 31 | react/react-in-jsx-scope: "off" 32 | react/no-array-index-key: 33 | - error 34 | array-callback-return: 35 | - error 36 | - allowImplicit: true 37 | react/jsx-no-duplicate-props: 38 | - error 39 | - ignoreCase: true 40 | react/jsx-no-undef: 41 | - error 42 | react/jsx-pascal-case: 43 | - error 44 | - allowAllCaps: true 45 | react/no-danger: 46 | - warn 47 | react/jsx-tag-spacing: 48 | - error 49 | - closingSlash: never 50 | beforeSelfClosing: always 51 | afterOpening: never 52 | beforeClosing: never 53 | react/no-unused-state: 54 | - error 55 | react/button-has-type: 56 | - error 57 | - button: true 58 | submit: true 59 | reset: false 60 | react-hooks/rules-of-hooks: 61 | - error 62 | react-hooks/exhaustive-deps: 63 | - error 64 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Deploy EczaneFront 2 | 3 | on: 4 | push: 5 | branches: ["prod"] 6 | 7 | jobs: 8 | deploy: 9 | name: Deploy 10 | runs-on: ubuntu-latest 11 | environment: prod 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: Configure AWS credentials 18 | uses: aws-actions/configure-aws-credentials@v1 19 | with: 20 | aws-access-key-id: ${{ secrets.PROD_AWS_ACCESS_KEY_ID }} 21 | aws-secret-access-key: ${{ secrets.PROD_AWS_SECRET_ACCESS_KEY }} 22 | aws-region: eu-central-1 23 | 24 | - name: Login to Amazon ECR 25 | id: login-ecr 26 | uses: aws-actions/amazon-ecr-login@v1 27 | 28 | - name: Build, tag, and push image to Amazon ECR 29 | id: build-image 30 | env: 31 | ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} 32 | ECR_REPOSITORY: eczane-web-ecr 33 | IMAGE_TAG: ${{ github.sha }} 34 | run: | 35 | # Build a docker container and 36 | # push it to ECR so that it can 37 | # be deployed to ECS. 38 | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . 39 | docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 40 | echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" 41 | 42 | - name: Fill in the new image ID in the Amazon ECS task definition 43 | id: task-def 44 | uses: aws-actions/amazon-ecs-render-task-definition@v1 45 | with: 46 | task-definition: task-definition.json 47 | container-name: container-name 48 | image: ${{ steps.build-image.outputs.image }} 49 | 50 | - name: Deploy Amazon ECS task definition 51 | uses: aws-actions/amazon-ecs-deploy-task-definition@v1 52 | with: 53 | task-definition: ${{ steps.task-def.outputs.task-definition }} 54 | service: eczane-front-service 55 | cluster: base-cluster 56 | wait-for-service-stability: true 57 | 58 | - name: CloudFlare Purge cache 59 | uses: nathanvaughn/actions-cloudflare-purge@master 60 | with: 61 | cf_zone: ${{ secrets.CLOUDFLARE_ZONE }} 62 | cf_auth: ${{ secrets.CLOUDFLARE_AUTH_KEY }} 63 | hosts: | 64 | saglik.afetharita.com 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | .idea/ 4 | .next/ -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "semi": true 5 | } 6 | -------------------------------------------------------------------------------- /AcikKaynakPR.md: -------------------------------------------------------------------------------- 1 | # Fork'lanan Repo'ya PR Açma 2 | 3 | Bu kaynak size ait olmayan açık kaynaklı bir repo'ya PR açmanız için adımları tanımlar. 4 | 5 | - Projenin ana repository'si https://github.com/acikkaynak/eczane-frontend adresinde bulunmakta. Ancak geliştiricilerin bir çoğunun bu repo'ya write-access'i bulunmamakta. Bu durumda bu reponun kendisini clone'layabilsek bile, burada halihazırda bulundan bir branch'e push yapmamız ya da yeni bir branch açıp ona push yapmamız mümkün değil ve bu noktada, standart günlük işimizde ilerlediğimiz adımlara ekstra bir kaç şey yapmamız gerekiyor. 6 | 7 | ## Projeyi Fork'lamak 8 | 9 | - İlk adım projeyi kendi github adresimize forklamak olmalı. Kendi adresimizde bulunan repo'da her türlü access'e sahip olacağımız için yukarda belirtilen sorunlarla karşılaşmayacağız. Projenin adresinde sağ üstte bulunan `Fork` butonuyla kolayca fork'layabilirsiniz. Her developerın sadece bir kez yapması gereken bir adım. 10 | 11 | ## Fork'lanan Projeyi Clone'lamak 12 | 13 | - İkinci adım kendi adresimize fork'ladığımız remote repo'yu local'e almak olacak. Bu standart bir clone'lama işlemi. Sadece reponun kendisini değil de fork'unu clonu'luyoruz. 14 | 15 | ## Branch'leme 16 | 17 | - Projenin ana branch'inden (main), o an yaptığımız task'ı belirtecek kısa bir isimle yeni bir branch oluşturuyoruz ve geliştirmeleri bu branch'te yapıyoruz. Geliştirmeler uzun sürecek ise, daha kısa hale getirip daha sık commit'ler ve PR'lar açmak, özellikle hızlı ilerlemesi gereken projelerde daha avantajlı olacak. 18 | 19 | ## Repoları Sync'leme 20 | 21 | - Her bir kaç saatte bir (gerektiğinde daha sık) main branch'ini kendi çalıştığımız branch'e merge'lemek, conflict oluşturmamak ve oluşanları küçük küçük çözmek için önemli. Bu kısımda yine normalde yaptığımız `git fetch` - `git merge` ikilisi tek başına işe yaramayacak çünkü bizim origin'imizde (fork'ladığımız repo) bizden başka çalışan yok. 22 | - Bu durumda "fetch - merge" öncesi, ana repoyla forkladığımız repoyu sync etmemiz gerekmekte. Bunun için fork'ladığımız reponun adresine gidip, `Sync Fork` butonuyla kolayca ana repodaki değişiklikleri kendi repomuza almış olacağız. Yani main'e X kişisinin yaptığı katkı, fork'ladığımız reponun main branch'ine de geçecek. 23 | - Bu adımın arkasından "pull" veya "fetch - merge" kullanarak (burada origin/main'i kendi çalıştığımız branch'e merge ediyoruz ve oluştuysa conflict'leri o an çözüyoruz), ana repodaki değişiklikleri kendi branch'imize almış oluyoruz. 24 | 25 | ## PR açma 26 | 27 | - Geliştirme tamamlandığında, fork'ladığımız repoda kendi branch'imize push'luyoruz ve ana repo'da main'den önde olup olmadığımızı kontrol ederek (sync adımı), ana reponun adresine gidiyoruz. Ana reponun adresinde zaten fork'lanmış bir repodaki hareketi github algıladığı için, PR açmamız için bizi büyük bir yeşil buton karşılıyor ve burada fork'lanan reponun branch'inden, ana reponun ana branch'ine (main) PR'ımızı açıyoruz. 28 | - PR'ımız merge'lendiğinde, sync ederek devam ediyoruz. 29 | - Açılan PR'larda sağ altta yer alan `Allow edit by maintainers`ı işaretleyiniz. 30 | 31 | image 32 | 33 | 34 | 35 | 36 | 37 | ## Dikkat Edilmesi Gereken Hususlar 38 | 39 | - Conflict içeren bir PR açmamak. 40 | - Çok uzun sürecek task'ları küçük task'lara ve branch'lere bölmek. 41 | - En fazla her saatte bir sync işlemini yapmak (aksi sizi yorar) 42 | - Açıklayıcı commit mesajları. 50 karaktere kadar kullanın, zararı olmaz. 43 | - Küçük commit'ler. Review için faydası olur. Her adımınızı tek tek review etmek daha kolay olacak. 44 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Standartlar 2 | 3 | ## Dışardan Katkı Sağlamak İçin 4 | [https://github.com/acikkaynak/eczane-frontend/issues](https://github.com/acikkaynak/eczane-frontend/issues) üzerinden `to-do` ve `help-wanted` label'larının mevcut olduğu herhangi bir issue altında direkt assign talep edebilirsiniz. Issues sıklıkla kontrol ediliyor. Çok gecikme yaşamadan katkı sağlamaya başlayabilirsiniz. Teşekkürler. 5 | 6 | https://github.com/acikkaynak/eczane-frontend/blob/main/AcikKaynakPR.md Açık Kaynak PR açma kılavuzunu da okumanız tavsiye olunur. 7 | 8 | ## CSS standartlari 9 | - Site genelinde kullanılan style'lar hariç düz css dosyaları kullanmayalım. MUI kesinlikle kullanmıyoruz. Dokunduğunuz dosyaların MUI kısımlarını temizlemek faydalı olur. module.scss'e aktarıyoruz. 10 | - Çok küçük değerler haricinde px yerine rem kullanalım. Bu browser'ında yüksek font kullanan insanlar için (yaşlılar özellikle) kolaylık sağlayacak. px kullanırsak anlam ifade etmez. 11 | - !important kullandıysak, neden kullanmak zorunda kaldığımızı PR'da belirtelim. 12 | - BREAKPOINT'lerimiz aşağıdaki şekide ve mobile first CSS yazıyoruz. Gerekli durumda ekstra eklenebilir. PR'da belirtilmelidir eklendiyse. 13 | 14 | ``` 15 | const mobileThreshold = 768; 16 | const largeThreshold = 1024; 17 | const xLargeThreshold = 1440; 18 | const xxLargeThreshold = 1600; 19 | const xxxLargeThreshold = 1920; 20 | ``` 21 | 22 | ## React Standartları 23 | 24 | - Constant değerleri component'lar dışında büyük harfle tanımlayalım. Component içinde 37.125 değeri olmamalı. ya da tüm icon'lar component içinde tanımlanmamalı. 25 | - lib ve util'e aktarmamız gereken kısımları aktaralım. 26 | - Çok büyük component'lardan kaçınalım. Reusable bir parça varsa kesinlikle ayıralım. 27 | - utils'te yer alan fonksiyonlari bir kontrol edelim. Şu an çok az zaten ama reimplement etmeye gerek yok. 28 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16 as builder 2 | 3 | # Create app directory 4 | WORKDIR /usr/src/app 5 | # Install app dependencies 6 | COPY package*.json ./ 7 | 8 | RUN npm install 9 | # Bundle app source 10 | COPY . . 11 | 12 | RUN npm run build 13 | 14 | FROM nginx:latest 15 | COPY --from=builder /usr/src/app/build /usr/share/nginx/html 16 | COPY nginx.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eczane-frontend 2 | [For english](README_ENG.md) 3 | 4 | ## Kullanılan Teknoloji ve Sistemler 5 | - React 17 6 | - LeafletJS 7 | - NodeJS v16 8 | - Prettier 9 | - ESLint 10 | - Husky 11 | - module scss 12 | 13 | ## Kurulum 14 | ### Repoyu klonlama 15 | 16 | ``` 17 | git clone https://github.com/acikkaynak/eczane-frontend 18 | ``` 19 | 20 | ### Gereksinimler 21 | Proje için bilgisayarınızda [NodeJS (v16)](https://nodejs.org/en/download/) kurulu olmalıdır. 22 | Proje klonlandiktan sonra gerekli kütüphaneleri kurmak için: 23 | 24 | ``` 25 | npm install 26 | ``` 27 | 28 | ### Başlatma 29 | Projeyi başlatmak için: 30 | 31 | ``` 32 | npm start 33 | ``` 34 | 35 | ## Docker 36 | Aşağıdaki kısımdan portu, kendi bilgisayarınızda hangi portta açmak istiyorsanız onunla değiştirin. Örneğin: 3000 37 | 38 | ``` 39 | docker build -t eczane-frontend . 40 | docker run -dp 127.0.0.1::80 --rm --name eczane-frontend eczane-frontend 41 | ``` 42 | 43 | ## Back-End Projesi: [eczane-backend](https://github.com/acikkaynak/eczane-backend) 44 | ## Admin Front-End Projesi: [eczane-admin-frontend](https://github.com/acikkaynak/eczane-admin-frontend) 45 | -------------------------------------------------------------------------------- /README_ENG.md: -------------------------------------------------------------------------------- 1 | # eczane-frontend 2 | [For english](README_ENG.md) 3 | 4 | ## Technologies used 5 | - React 17 6 | - LeafletJS 7 | - NodeJS v16 8 | - MaterialUI (We used it but we are slowly removing it) 9 | - Prettier 10 | - TODO: ESLint 11 | 12 | ## Quick Start 13 | ### Cloning Repo 14 | 15 | ``` 16 | git clone https://github.com/acikkaynak/eczane-frontend 17 | ``` 18 | 19 | ### Requirements 20 | For project [NodeJS (v16)](https://nodejs.org/en/download/) should be installed in your computer. 21 | To install libraries after cloning project: 22 | 23 | ``` 24 | npm install 25 | ``` 26 | 27 | ### To start 28 | To run the project: 29 | 30 | ``` 31 | npm start 32 | ``` 33 | 34 | ## Docker 35 | In the section below, change the port to whichever port you want to open on your computer. For example 3000 36 | 37 | ``` 38 | docker build -t eczane-frontend . 39 | docker run -dp 127.0.0.1::80 --rm --name eczane-frontend eczane-frontend 40 | ``` 41 | 42 | ## Back-End Project: [eczane-backend](https://github.com/acikkaynak/eczane-backend) 43 | ## Admin Front-End Project [eczane-admin-frontend](https://github.com/acikkaynak/eczane-admin-frontend) 44 | -------------------------------------------------------------------------------- /dosya-aciklamalari.md: -------------------------------------------------------------------------------- 1 | kılavuz: 2 | 1-=https://mui.com/material-ui/react-box/ 3 | 2==https://mui.com/material-ui/react-stack/ 4 | 3==https://mui.com/material-ui/react-grid/ 5 | =
anlamına gelir 6 | =
ancak ayarlanmış div gibi mui kullanıcılarına kolaylık 7 | için yapılmış hali isterseniz
yapılabilir 8 | =html grid neredeyse tamamen aynı 9 | 10 | 11 | cityCenters.js=Şehierlin merkezlerinin olduğu array 12 | counterSlice.js=Provider ayarlaması için ellenmicek 13 | DownButton.js=Aşağı inmesini sağlayan button 14 | FilterIcon.js=icon 15 | FiltreYer.js=Eczane,Hastane,Hepsi ve eklenicek olan veterinerin olduğu yer 16 | Header.js =Başlangıç kısmı ve yazılar ordaki 17 | IlListesi.js=Mapın altında olan kısım 10 ilin yazdığı yer haritanın altındaki 18 | ListPage.js=Liste kısmında çıkan sayfanın tamamı burada 19 | LogoIcon.js=icon 20 | MainViewContainer.js=Her şeyin toplandığı yer 21 | Map.js=Haritanın tamamının olduğu yer 22 | SelectType.js=Haritada mı Listede mi gösteriliceğini seçtiğiniz yer 23 | UpButton.js=Yukarı çıkmasını sağlayan button 24 | useFetch.js=API dan request sağlayan custom hook 25 | store.js=Provider için ellenmicek dosya 26 | App.js=Ellenmesine gerek yok 27 | index.js=Eklenmesine gerek yok 28 | index.css=Ellenmesine gerek yok 29 | App.css=Uygulamada olan tüm cssler burada toplanıyor -------------------------------------------------------------------------------- /i18n.js: -------------------------------------------------------------------------------- 1 | import i18n from "i18next"; 2 | import LanguageDetector from "i18next-browser-languagedetector"; 3 | import Backend from "i18next-http-backend"; 4 | import { initReactI18next } from "react-i18next"; 5 | import translationEN from "./public/locales/en/common.json"; 6 | import translationTR from "./public/locales/tr/common.json"; 7 | import { LANGUAGE_KEY_LOCAL_STORAGE } from "./src/utils/constants"; 8 | import { getLocalStorage } from "./src/utils/hooks"; 9 | 10 | const resources = { 11 | EN: { 12 | common: translationEN, 13 | }, 14 | TR: { 15 | common: translationTR, 16 | }, 17 | }; 18 | 19 | i18n 20 | .use(Backend) 21 | .use(LanguageDetector) 22 | .use(initReactI18next) 23 | .init({ 24 | resources, 25 | fallbackLng: "TR", 26 | localeDetection: false, 27 | lng: getLocalStorage(LANGUAGE_KEY_LOCAL_STORAGE, "TR"), 28 | debug: false, 29 | preload: true, 30 | returnNull: false, 31 | ns: ["common"], 32 | detection: { 33 | order: ["localStorage", "cookie"], 34 | cache: ["cookie"], 35 | }, 36 | interpolation: { 37 | escapeValue: false, 38 | }, 39 | }); 40 | 41 | export default i18n; 42 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | location / { 4 | root /usr/share/nginx/html; 5 | index index.html index.htm; 6 | try_files $uri $uri/ /index.html =404; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "axios": "^1.3.2", 7 | "clsx": "^1.2.1", 8 | "formik": "^2.2.9", 9 | "i18next": "^22.4.10", 10 | "i18next-browser-languagedetector": "^7.0.1", 11 | "i18next-http-backend": "^2.1.1", 12 | "leaflet": "1.7.1", 13 | "leaflet.markercluster": "^1.5.3", 14 | "next": "12.0.0", 15 | "next-i18next": "^13.2.0", 16 | "prop-types": "^15.8.1", 17 | "react": "^17.0.2", 18 | "react-dom": "^17.0.2", 19 | "react-i18next": "^12.2.0", 20 | "react-icons": "^4.7.1", 21 | "react-leaflet": "3.0.2", 22 | "react-leaflet-custom-control": "^1.3.3", 23 | "react-leaflet-fullscreen": "^2.0.2", 24 | "react-leaflet-markercluster": "^3.0.0-rc1", 25 | "react-scripts": "5.0.1", 26 | "react-select": "^5.7.0", 27 | "sass": "^1.58.1", 28 | "web-vitals": "^2.1.4", 29 | "yup": "^1.0.0" 30 | }, 31 | "scripts": { 32 | "dev": "next dev", 33 | "build": "next build", 34 | "start": "next start", 35 | "prettier-fix": "prettier 'src/**/*.(ts|tsx|js|jsx|css|json)' --write", 36 | "lint": "eslint --fix --ext .js,.jsx,.ts,.tsx ./src", 37 | "prepare": "husky install" 38 | }, 39 | "lint-staged": { 40 | "**/*.{js,jsx,ts,tsx}": [ 41 | "npm run lint" 42 | ] 43 | }, 44 | "eslintConfig": { 45 | "extends": [ 46 | "react-app", 47 | "react-app/jest" 48 | ] 49 | }, 50 | "browserslist": { 51 | "production": [ 52 | ">0.2%", 53 | "not dead", 54 | "not op_mini all" 55 | ], 56 | "development": [ 57 | "last 1 chrome version", 58 | "last 1 firefox version", 59 | "last 1 safari version" 60 | ] 61 | }, 62 | "devDependencies": { 63 | "@babel/eslint-parser": "^7.19.1", 64 | "babel-eslint": "^10.1.0", 65 | "eslint": "^7.32.0", 66 | "eslint-config-prettier": "^8.6.0", 67 | "eslint-plugin-prettier": "^4.2.1", 68 | "eslint-plugin-react": "^7.32.2", 69 | "eslint-plugin-react-hooks": "^4.6.0", 70 | "husky": "^8.0.3", 71 | "lint-staged": "^13.1.2", 72 | "prettier": "^2.8.4" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import "../src/styles/App.scss"; 2 | import "leaflet/dist/leaflet.css"; 3 | import "react-leaflet-fullscreen/dist/styles.css"; 4 | import "leaflet.markercluster/dist/MarkerCluster.Default.css"; 5 | import "leaflet.markercluster/dist/MarkerCluster.css"; 6 | import PropTypes from "prop-types"; 7 | import { useTranslation } from "react-i18next"; 8 | 9 | import Head from "next/head"; 10 | 11 | export default function MyApp({ Component, pageProps }) { 12 | const { t } = useTranslation(); 13 | 14 | return ( 15 | <> 16 | 17 | {t("common:title")} 18 | 19 | 23 | 24 | 28 | 29 | 30 | 31 | ); 32 | } 33 | 34 | MyApp.propTypes = { 35 | Component: PropTypes.elementType.isRequired, 36 | pageProps: PropTypes.object.isRequired, 37 | }; 38 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Head, Html, Main, NextScript } from "next/document"; 2 | import { LANGUAGE_KEY_LOCAL_STORAGE } from "../src/utils/constants"; 3 | import { getLocalStorage } from "../src/utils/hooks"; 4 | 5 | class MyDocument extends Document { 6 | static async getInitialProps(ctx) { 7 | const originalRenderPage = ctx.renderPage; 8 | 9 | // Run the React rendering logic synchronously 10 | ctx.renderPage = () => 11 | originalRenderPage({ 12 | // Useful for wrapping the whole react tree 13 | enhanceApp: (App) => App, 14 | // Useful for wrapping in a per-page basis 15 | enhanceComponent: (Component) => Component, 16 | }); 17 | 18 | // Run the parent `getInitialProps`, it now includes the custom `renderPage` 19 | const initialProps = await Document.getInitialProps(ctx); 20 | 21 | return initialProps; 22 | } 23 | 24 | render() { 25 | return ( 26 | 27 | 28 | 29 | 33 | 37 | 38 | 43 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | ); 54 | } 55 | } 56 | 57 | export default MyDocument; 58 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import dynamic from "next/dynamic"; 2 | import React, { useMemo, useState } from "react"; 3 | 4 | import "../i18n"; 5 | 6 | import ListPage from "../src/components/ListPage/ListPage"; 7 | import centers from "../src/lib/cityCenters"; 8 | 9 | import axios from "axios"; 10 | import propTypes from "prop-types"; // ES6 11 | 12 | import { TypeDataContext } from "../src/lib/typeDataContext"; 13 | import { calculateCenter } from "../src/utils/calculateCenter"; 14 | import { HEPSI_ID, SEARCH_AT } from "../src/utils/constants.js"; 15 | 16 | const MapPage = dynamic(() => import("../src/components/MapPage/MapPage"), { 17 | loading: () =>

loading...

, 18 | ssr: false, 19 | }); 20 | 21 | const HeaderCombined = dynamic( 22 | () => import("../src/components/Header/HeaderCombined"), 23 | { 24 | ssr: false, 25 | } 26 | ); 27 | 28 | const Footer = dynamic(() => import("../src/components/Footer/Footer"), { 29 | ssr: false, 30 | }); 31 | 32 | const Homepage = ({ fetchedData, cityData, typeData }) => { 33 | const centerLatLong = calculateCenter(fetchedData); 34 | 35 | const allData = fetchedData?.data; 36 | 37 | const [map, setMap] = useState(); 38 | 39 | const [searchAt, setSearchAt] = useState(SEARCH_AT.HARITA); 40 | const [filter, setFilter] = useState(HEPSI_ID); 41 | const [searchBarVal, setSearchbarVal] = useState(""); 42 | const [selectedCity, setSelectedCity] = useState(null); 43 | const [selectedDist, setSelectedDist] = useState(null); 44 | 45 | const handleLock = () => { 46 | if (map.dragging.enabled()) { 47 | map.dragging.disable(); 48 | map.zoomControl.disable(); 49 | map.scrollWheelZoom.disable(); 50 | } else { 51 | map.dragging.enable(); 52 | map.zoomControl.enable(); 53 | map.scrollWheelZoom.enable(); 54 | } 55 | }; 56 | 57 | const handleChangeCity = (city) => { 58 | if (city == null) { 59 | setSelectedCity(null); 60 | setSelectedDist(null); 61 | map.flyTo([centerLatLong.latitude, centerLatLong.longitude], 7); 62 | return; 63 | } 64 | const lat = centers[city.key]?.lat; 65 | const lng = centers[city.key]?.lng; 66 | map.flyTo([lat, lng], 12); 67 | setSelectedCity(city.id); 68 | setSelectedDist(null); 69 | }; 70 | 71 | const districtMap = useMemo(() => { 72 | const theMap = new Map(); 73 | const allDistricts = cityData?.data?.map((city) => city.districts).flat(); 74 | allDistricts?.forEach((district) => { 75 | theMap.set(district.id, district.key); 76 | }); 77 | return theMap; 78 | }, [cityData]); 79 | 80 | const typeFilteredData = allData?.filter( 81 | (item) => filter === HEPSI_ID || item.typeId === filter 82 | ); 83 | const searchFilteredData = typeFilteredData?.filter( 84 | (item) => 85 | item.name.toLowerCase().includes(searchBarVal.toLowerCase()) || 86 | item.address.toLowerCase().includes(searchBarVal.toLowerCase()) 87 | ); 88 | const cityFilteredData = 89 | selectedCity == null 90 | ? searchFilteredData 91 | : searchFilteredData?.filter((item) => item.cityId === selectedCity); 92 | 93 | const distFilteredData = 94 | selectedDist == null 95 | ? cityFilteredData 96 | : cityFilteredData?.filter((item) => item.districtId === selectedDist); 97 | 98 | const hasDataObj = typeData?.data?.map((type) => { 99 | const dataExists = allData?.some((item) => item.typeId === type.id); 100 | return { typeId: type.id, hasData: dataExists }; 101 | }); 102 | 103 | return ( 104 |
105 | 106 | 115 | 116 | {searchAt === SEARCH_AT.HARITA && ( 117 | 118 | 125 | 126 | )} 127 | {searchAt === SEARCH_AT.LISTE && ( 128 | 129 | 134 | 135 | )} 136 | 137 |
146 |
147 | ); 148 | }; 149 | 150 | export async function getStaticProps() { 151 | const fetchedData = await axios.get( 152 | "https://eczaneapi.afetharita.com/api/locations" 153 | ); 154 | 155 | const cityData = await axios.get( 156 | "https://eczaneapi.afetharita.com/api/cityWithDistricts" 157 | ); 158 | 159 | const typeData = await axios.get( 160 | "https://eczaneapi.afetharita.com/api/types" 161 | ); 162 | 163 | return { 164 | props: { 165 | fetchedData: fetchedData.data, 166 | cityData: cityData.data, 167 | typeData: typeData.data, 168 | }, 169 | revalidate: 10, 170 | }; 171 | } 172 | 173 | Homepage.propTypes = { 174 | fetchedData: propTypes.object, 175 | cityData: propTypes.object, 176 | typeData: propTypes.object, 177 | }; 178 | 179 | export default Homepage; 180 | -------------------------------------------------------------------------------- /public/icons/Lock.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/icons/afet-harita.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/afet-harita.webp -------------------------------------------------------------------------------- /public/icons/deprem-io.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/deprem-io.webp -------------------------------------------------------------------------------- /public/icons/deprem-yardim.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/icons/deprem-yardim.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/deprem-yardim.webp -------------------------------------------------------------------------------- /public/icons/deprem_io.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/icons/filter-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/icons/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/fullscreen.png -------------------------------------------------------------------------------- /public/icons/fullscreen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/icons/hospital-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/hospital-1.png -------------------------------------------------------------------------------- /public/icons/hospital-1.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/icons/hospital-marker-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/hospital-marker-2.png -------------------------------------------------------------------------------- /public/icons/hospital-marker-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/icons/hospital-marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/hospital-marker.png -------------------------------------------------------------------------------- /public/icons/hospital-marker.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/icons/hospital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/hospital.png -------------------------------------------------------------------------------- /public/icons/hospital.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/left-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/lockOpen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | lock-open 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /public/icons/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/pharmacy-marker-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/pharmacy-marker-2.png -------------------------------------------------------------------------------- /public/icons/pharmacy-marker-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/icons/pharmacy-marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/pharmacy-marker.png -------------------------------------------------------------------------------- /public/icons/pharmacy-marker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/icons/pill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/pill.png -------------------------------------------------------------------------------- /public/icons/pill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/icons/search-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/show-all-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/vet copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/vet copy.png -------------------------------------------------------------------------------- /public/icons/vet copy.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/icons/vet-marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/vet-marker.png -------------------------------------------------------------------------------- /public/icons/vet-marker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/icons/vet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/icons/vet.png -------------------------------------------------------------------------------- /public/icons/vet.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/images/header-bg-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/images/header-bg-desktop.jpg -------------------------------------------------------------------------------- /public/images/header-bg-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/images/header-bg-mobile.jpg -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/public/images/logo.png -------------------------------------------------------------------------------- /public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 16 | 17 | 22 | 26 | Afet Sağlık 27 | 31 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /public/locales/en/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Disaster Health", 3 | "search": "Search", 4 | "mapBtn": "Show on map", 5 | "listBtn": "Show in list", 6 | "allBtn": "All", 7 | "showAll": "Show all", 8 | "hospitalBtn": "Hospital", 9 | "pharmacyBtn": "Pharmacy", 10 | "vetBtn": "Vet", 11 | "psychologistBtn": "Psychological Support", 12 | "chooseACity": "Choose a City", 13 | "helperSites": "Helper Sites" 14 | } -------------------------------------------------------------------------------- /public/locales/tr/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Afet Sağlık", 3 | "search": "Ara", 4 | "mapBtn": "Haritada", 5 | "listBtn": "Listede", 6 | "allBtn": "Hepsi", 7 | "showAll": "Tümünü Gör", 8 | "hospitalBtn": "Hastane", 9 | "pharmacyBtn": "Eczane", 10 | "vetBtn": "Veteriner", 11 | "psychologistBtn": "Psikolojik Destek", 12 | "chooseACity": "Şehir Seçiniz", 13 | "helperSites": "Yardımcı Siteler" 14 | } -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: https://saglik.afetharita.com/sitemap.xml 5 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://saglik.afetharita.com/ 5 | 2023-02-16T17:52:45+00:00 6 | 7 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./App.scss"; 3 | import MainViewContaier from "./components/MainViewContainer/MainViewContainer"; 4 | 5 | export default function App() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/DragIcon/DragIcon.js: -------------------------------------------------------------------------------- 1 | import PropTypes from "prop-types"; // ES6 2 | import Control from "react-leaflet-custom-control"; 3 | import { debounce } from "../../utils/debounce"; 4 | import styles from "./DragIcon.module.scss"; 5 | 6 | const DragIcon = ({ dragActive, onLockClick }) => ( 7 | 8 | 21 | 22 | ); 23 | 24 | DragIcon.propTypes = { 25 | dragActive: PropTypes.bool.isRequired, 26 | onLockClick: PropTypes.func.isRequired, 27 | }; 28 | 29 | export default DragIcon; 30 | -------------------------------------------------------------------------------- /src/components/DragIcon/DragIcon.module.scss: -------------------------------------------------------------------------------- 1 | .button { 2 | all: unset; 3 | cursor: pointer; 4 | } 5 | 6 | .iconWrapper { 7 | width: 30px; 8 | height: 30px; 9 | border-radius: 3px; 10 | background-color: #fff; 11 | background-position: 50% 50%; 12 | background-repeat: no-repeat; 13 | border: 2px solid rgba(0, 0, 0, 0.2); 14 | 15 | span { 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | &::before { 20 | width: calc(15px + 0.390625vw); 21 | padding: 6px; 22 | } 23 | } 24 | .lockIcon { 25 | &::before { 26 | content: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3Csvg fill='%23000000' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 8V6a6 6 0 1 1 12 0v2h1a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-8c0-1.1.9-2 2-2h1zm5 6.73V17h2v-2.27a2 2 0 1 0-2 0zM7 6v2h6V6a3 3 0 0 0-6 0z'/%3E%3C/svg%3E"); 27 | } 28 | } 29 | .lockOpenIcon { 30 | &::before { 31 | content: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3Csvg viewBox='0 0 48 48' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3Elock-open%3C/title%3E%3Cg id='Layer_2' data-name='Layer 2'%3E%3Cg id='invisible_box' data-name='invisible box'%3E%3Crect width='48' height='48' fill='none'/%3E%3C/g%3E%3Cg id='icons_Q2' data-name='icons Q2'%3E%3Cg%3E%3Cpath d='M32,21.9h0Z'/%3E%3Cpath d='M40,18H16V13a7,7,0,0,1,7-7h2a7.1,7.1,0,0,1,5,2.1,2,2,0,0,0,2.2.5h.1a1.9,1.9,0,0,0,.6-3.1A10.9,10.9,0,0,0,25,2H23A11,11,0,0,0,12,13v5H8a2,2,0,0,0-2,2V44a2,2,0,0,0,2,2H40a2,2,0,0,0,2-2V20A2,2,0,0,0,40,18ZM38,42H10V22H38Z'/%3E%3Cpath d='M27.9,29.9a4,4,0,1,0-6,3.5v2.5a2,2,0,0,0,4,0V33.4A4,4,0,0,0,27.9,29.9Z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | import PropTypes from "prop-types"; // ES6 2 | import React from "react"; 3 | import Block from "../../lib/Block/Block"; 4 | import { useWindowSize } from "../../utils/hooks"; 5 | import Others from "../Others/Others"; 6 | import styles from "./Footer.module.scss"; 7 | import { useTranslation } from "next-i18next"; 8 | 9 | const Footer = ({ 10 | cityData, 11 | selectedCity, 12 | handleChangeCity, 13 | selectedDist, 14 | setSelectedDist, 15 | allData, 16 | hideDistrictSelector, 17 | }) => { 18 | const { isDesktop } = useWindowSize(); 19 | 20 | const noCitySelected = !selectedCity; 21 | 22 | const selectedCityData = cityData?.data?.find((a) => a.id === selectedCity); 23 | 24 | const selectedCityDistricts = selectedCityData?.districts; 25 | 26 | const allCities = cityData?.data; 27 | 28 | const cityDistrictWithData = selectedCityDistricts 29 | ?.filter((dist) => { 30 | if (!selectedCityDistricts) return true; 31 | const distData = allData?.find((d) => d.districtId === dist.id); 32 | return !!distData; 33 | }) 34 | .map((i) => i.key); 35 | const { t } = useTranslation(); 36 | 37 | return ( 38 | 39 |
40 | {!hideDistrictSelector && ( 41 |
42 |
43 |
44 |
45 |
46 | {noCitySelected && ( 47 |
48 |

{t("common:chooseACity")}

49 |
50 | )} 51 | {selectedCityDistricts?.map((item) => ( 52 | 69 | ))} 70 |
71 |
72 |
73 |
74 |
75 | )} 76 | 77 |
78 | {allCities?.map((item) => ( 79 | 91 | ))} 92 | {!isDesktop && ( 93 | 100 | )} 101 |
102 | {isDesktop && ( 103 |
handleChangeCity(null)} 106 | > 107 | 113 |
114 | )} 115 | 116 |
117 | 118 |
119 |
120 |
121 | ); 122 | }; 123 | Footer.propTypes = { 124 | cityData: PropTypes.object, 125 | selectedCity: PropTypes.number, 126 | handleChangeCity: PropTypes.func.isRequired, 127 | selectedDist: PropTypes.number, 128 | setSelectedDist: PropTypes.func.isRequired, 129 | allData: PropTypes.array, 130 | hideDistrictSelector: PropTypes.bool.isRequired, 131 | }; 132 | 133 | export default Footer; 134 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.module.scss: -------------------------------------------------------------------------------- 1 | .footerContainer { 2 | padding-top: 59px; 3 | max-width: 1399px; 4 | width: 85%; 5 | min-width: 340px; 6 | margin: 0 auto; 7 | display: flex; 8 | flex-direction: column; 9 | @media screen and (max-width: 768px) { 10 | padding-top: 19px; 11 | min-width: 325px; 12 | max-width: 500px; 13 | margin: 0 auto; 14 | display: flex; 15 | flex-direction: column; 16 | } 17 | } 18 | 19 | .IconWrapper { 20 | display: none; 21 | align-items: center; 22 | 23 | .button { 24 | background: none; 25 | color: inherit; 26 | border: none; 27 | padding: 0; 28 | font: inherit; 29 | cursor: pointer; 30 | outline: inherit; 31 | 32 | &:global(.left) { 33 | &::before { 34 | vertical-align: middle; 35 | display: inline-block; 36 | width: calc(12px + 0.390625vw); 37 | height: calc(15px + 0.390625vw); 38 | align-items: center; 39 | content: url("data:image/svg+xml,%3Csvg id='Group_10197' data-name='Group 10197' xmlns='http://www.w3.org/2000/svg' width='25.651' height='22.352' viewBox='0 0 25.651 22.352'%3E%3Cpath id='Path_270' data-name='Path 270' d='M.469.47a1.6,1.6,0,0,1,2.26,0l8.447,8.449L19.624.468a1.6,1.6,0,1,1,2.26,2.26l-9.577,9.577a1.6,1.6,0,0,1-2.26,0L.469,2.728a1.6,1.6,0,0,1,0-2.26Z' transform='translate(12.775 0) rotate(90)' fill='%23fff' fill-rule='evenodd'/%3E%3Cpath id='Path_271' data-name='Path 271' d='M1.6,0c.882,0,1.6.5,1.6,1.123V21.333c0,.62-.715,1.123-1.6,1.123S0,21.954,0,21.333V1.123C0,.5.715,0,1.6,0Z' transform='translate(25.651 9.58) rotate(90)' fill='%23fff' fill-rule='evenodd'/%3E%3C/svg%3E"); 40 | } 41 | } 42 | 43 | &:global(.right) { 44 | &::after { 45 | vertical-align: middle; 46 | display: inline-block; 47 | width: calc(12px + 0.390625vw); 48 | height: calc(15px + 0.390625vw); 49 | align-items: center; 50 | margin-right: 10px; 51 | content: url("data:image/svg+xml,%3Csvg width='26' height='23' viewBox='0 0 26 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.3487 21.9424C13.0495 21.6425 12.8815 21.2361 12.8815 20.8124C12.8815 20.3887 13.0495 19.9824 13.3487 19.6824L21.7977 11.2354L13.3467 2.78742C13.1861 2.64188 13.0567 2.46523 12.9665 2.26819C12.8762 2.07114 12.8269 1.8578 12.8215 1.64112C12.8162 1.42444 12.855 1.20894 12.9354 1.00769C13.0159 0.806436 13.1364 0.623632 13.2897 0.47037C13.443 0.317108 13.6258 0.196583 13.827 0.116109C14.0283 0.035635 14.2438 -0.00310998 14.4604 0.00222492C14.6771 0.00755983 14.8905 0.0568629 15.0875 0.147143C15.2846 0.237424 15.4612 0.366799 15.6067 0.527417L25.1837 10.1044C25.483 10.4044 25.651 10.8107 25.651 11.2344C25.651 11.6581 25.483 12.0645 25.1837 12.3644L15.6067 21.9424C15.3068 22.2416 14.9004 22.4097 14.4767 22.4097C14.0531 22.4097 13.6467 22.2416 13.3467 21.9424H13.3487Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0.00274277 11.2314C0.00274277 10.3494 0.502742 9.63142 1.12574 9.63142H21.3357C21.9557 9.63142 22.4587 10.3464 22.4587 11.2314C22.4587 12.1164 21.9567 12.8314 21.3357 12.8314H1.12574C0.502742 12.8314 0.00274277 12.1164 0.00274277 11.2314Z' fill='white'/%3E%3C/svg%3E"); 52 | } 53 | } 54 | } 55 | } 56 | 57 | .paragWrapper { 58 | display: flex; 59 | justify-content: center; 60 | align-items: center; 61 | @media (min-width: "768px") { 62 | font-size: 2.25rem; 63 | } 64 | } 65 | 66 | .parag { 67 | font-family: Roboto, sans-serif; 68 | font-size: 0.75rem; 69 | color: white; 70 | @media (min-width: "768px") { 71 | font-size: 2.25rem; 72 | } 73 | } 74 | 75 | .showAllIcon { 76 | position: absolute; 77 | right: 0.5rem; 78 | top: 50%; 79 | transform: translateY(-50%); 80 | height: 0.75rem; 81 | width: 0.75rem; 82 | @media (min-width: "768px") { 83 | height: 1.5rem; 84 | width: 1.5rem; 85 | right: 1rem; 86 | } 87 | } 88 | 89 | .ilceBox { 90 | padding: 8px 8px; 91 | border: 1px solid white; 92 | border-radius: 5px; 93 | overflow-x: hidden; 94 | display: flex; 95 | width: 100%; 96 | align-items: center; 97 | margin: 0 auto; 98 | @media screen and (max-width: 768px) { 99 | padding: 0.5rem 0; 100 | border: 1px solid white; 101 | border-radius: 5px; 102 | overflow-x: hidden; 103 | display: flex; 104 | justify-content: space-between; 105 | min-height: 2.25rem; 106 | } 107 | } 108 | 109 | .ilceItems { 110 | position: relative; 111 | padding: 0 15px; 112 | flex-grow: 1; 113 | @media screen and (max-width: 768px) { 114 | overflow-x: auto; 115 | } 116 | } 117 | 118 | .ilceItem { 119 | font-family: "Roboto", sans-serif; 120 | background-color: inherit; 121 | outline: none; 122 | border: none; 123 | color: white; 124 | font-size: 2.125rem; 125 | padding: 0.5rem 1.25rem; 126 | border-radius: 0.625rem; 127 | user-select: none; 128 | cursor: pointer; 129 | @media screen and (max-width: 768px) { 130 | background-color: inherit; 131 | outline: none; 132 | border: none; 133 | color: white; 134 | font-size: 0.75rem; 135 | padding: 0.5rem 0.75rem; 136 | } 137 | } 138 | 139 | .citiesBox { 140 | padding: 0.875rem 0; 141 | gap: 0.625rem; 142 | width: 100%; 143 | display: grid; 144 | overflow: hidden; 145 | grid-template-columns: repeat(5, 1fr); 146 | @media screen and (max-width: 1280px) { 147 | grid-template-columns: repeat(4, 1fr); 148 | } 149 | @media screen and (max-width: 1024px) { 150 | grid-template-columns: repeat(3, 1fr); 151 | } 152 | @media screen and (max-width: 768px) { 153 | display: flex; 154 | flex-wrap: wrap; 155 | justify-content: space-between; 156 | } 157 | @media (min-width: 310px) and (max-width: 510px) { 158 | width: 100%; 159 | margin: 0 auto; 160 | } 161 | } 162 | 163 | .ilceActive { 164 | background-color: #f83b3b; 165 | border-radius: 5px; 166 | } 167 | 168 | .ilceDisabled { 169 | color: #888; 170 | cursor: not-allowed; 171 | } 172 | 173 | .cityItem { 174 | font-family: "Roboto", sans-serif; 175 | border: none; 176 | background-color: inherit; 177 | color: white; 178 | font-size: 2rem; 179 | border: 1px white solid; 180 | border-radius: 0.625rem; 181 | padding: 0.4rem; 182 | flex-grow: 1; 183 | user-select: none; 184 | cursor: pointer; 185 | @media screen and (max-width: 768px) { 186 | flex: 0 1 30%; 187 | max-width: 450px; 188 | font-size: 0.75rem; 189 | width: 110px; 190 | padding: 0.325rem; 191 | } 192 | @media (min-width: 310px) and (max-width: 510px) { 193 | max-width: 150px; 194 | font-size: 11px; 195 | overflow: hidden; 196 | } 197 | } 198 | 199 | .cityItemActive { 200 | background-color: white; 201 | color: inherit; 202 | } 203 | 204 | .leftArrow { 205 | background-color: inherit; 206 | border: none; 207 | } 208 | .rightArrow { 209 | background-color: inherit; 210 | border: none; 211 | } 212 | 213 | .seeAllWrapper { 214 | position: relative; 215 | } 216 | 217 | .seeAllButton { 218 | @extend .cityItem; 219 | display: flex; 220 | align-items: center; 221 | justify-content: center; 222 | margin-left: auto; 223 | white-space: nowrap; 224 | background: #f83b3b; 225 | border: none; 226 | border-radius: 0.625rem; 227 | 228 | &::after { 229 | width: calc(20px + 0.390625vw); 230 | height: calc(30px + 0.390625vw); 231 | padding: 0 5px; 232 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 80 80' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.96924 79.0308C-0.118327 77.9432 -0.118327 76.1799 0.969238 75.0924L74.0924 1.96921C75.18 0.881644 76.9433 0.881647 78.0308 1.96921C79.1184 3.05678 79.1184 4.82007 78.0308 5.90763L4.90766 79.0308C3.8201 80.1184 2.05681 80.1184 0.96924 79.0308Z' fill='white'/%3E%3Cpath d='M80 76.2421C80 77.7652 78.7653 79 77.2421 79C75.7189 79 74.4842 77.7652 74.4842 76.2421V10.6527C74.4842 7.89133 72.2456 5.65274 69.4842 5.65274H3.8264C2.26544 5.65274 1.00003 4.38733 1.00003 2.82637C1.00003 1.26541 2.26544 0 3.8264 0H74.9993C77.7607 0 79.9993 2.23855 79.9993 4.99995L80 76.2421Z' fill='white'/%3E%3C/svg%3E"); 233 | } 234 | } 235 | 236 | .othersWrapper { 237 | display: flex; 238 | justify-content: center; 239 | margin-top: 0.5rem; 240 | 241 | @media screen and (min-width: 769px) { 242 | justify-content: flex-start; 243 | } 244 | } 245 | 246 | .seeAllMobile { 247 | @extend .cityItem; 248 | padding: 0; 249 | background-color: red !important; 250 | border: none !important; 251 | outline: none !important; 252 | 253 | @media screen and (min-width: 769px) { 254 | &::after { 255 | vertical-align: middle; 256 | display: inline-block; 257 | width: calc(12px + 0.390625vw); 258 | height: calc(15px + 0.390625vw); 259 | align-items: center; 260 | margin-right: 10px; 261 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29.308' height='29.308' viewBox='0 0 29.308 29.308'%3E%3Cg id='Icon_feather-arrow-up-right' data-name='Icon feather-arrow-up-right' transform='translate(1.061 1.061)'%3E%3Cpath id='Path_264' data-name='Path 264' d='M10.5,37.686,37.686,10.5' transform='translate(-10.5 -10.5)' fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5'/%3E%3Cpath id='Path_265' data-name='Path 265' d='M10.5,10.5H37.686V37.686' transform='translate(-10.5 -10.5)' fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5'/%3E%3C/g%3E%3C/svg%3E"); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /src/components/FullScreenIcon/FullScreenIcon.js: -------------------------------------------------------------------------------- 1 | import Control from "react-leaflet-custom-control"; 2 | import { FullscreenControl } from "react-leaflet-fullscreen"; 3 | 4 | const FullScreenIcon = () => ( 5 | 6 | 12 | 13 | ); 14 | 15 | export default FullScreenIcon; 16 | -------------------------------------------------------------------------------- /src/components/Header/Header/Header.js: -------------------------------------------------------------------------------- 1 | import { useTranslation } from "next-i18next"; 2 | import React from "react"; 3 | import Select from "react-select"; 4 | import "../../../../i18n"; 5 | import { LANGUAGE_KEY_LOCAL_STORAGE } from "../../../utils/constants"; 6 | import { useLocalStorage } from "../../../utils/hooks"; 7 | import styles from "./Header.module.scss"; 8 | 9 | const Header = () => { 10 | const { t, i18n } = useTranslation(); 11 | const [storedLanguage, setStoredLanguage] = useLocalStorage( 12 | LANGUAGE_KEY_LOCAL_STORAGE, 13 | "TR" 14 | ); 15 | 16 | const handleChangeLang = (lang) => { 17 | i18n.changeLanguage(lang.value); 18 | setStoredLanguage(lang.value); 19 | }; 20 | const options = [ 21 | { value: "TR", label: "TR" }, 22 | { value: "EN", label: "EN" }, 23 | ]; 24 | 25 | return ( 26 |
27 |
28 | logo 36 |

{t("common:title")}

37 |
38 |
39 | setSearchBarVal(e.target.value)} 14 | className={styles.input} 15 | /> 16 |
17 | 24 |
25 |
26 | ); 27 | }; 28 | 29 | SearchBar.propTypes = { 30 | searchBarVal: PropTypes.string.isRequired, 31 | setSearchBarVal: PropTypes.func.isRequired, 32 | }; 33 | 34 | export default SearchBar; 35 | -------------------------------------------------------------------------------- /src/components/Header/SearchBar.module.scss: -------------------------------------------------------------------------------- 1 | .searchBoxWrapper { 2 | position: relative; 3 | flex-grow: 1; 4 | 5 | @media (min-width: 769px) { 6 | flex-grow: 0; 7 | min-width: 350px; 8 | } 9 | 10 | @media (min-width: 1025px) { 11 | min-width: 500px; 12 | } 13 | 14 | @media (min-width: 1441px) { 15 | // min-width: 750px; 16 | // flex-grow: 1; 17 | } 18 | } 19 | 20 | .input { 21 | height: 100%; 22 | box-sizing: border-box; 23 | border-radius: 0.625rem; 24 | padding: 0.5rem; 25 | outline: none; 26 | border: 1px solid white; 27 | width: 100%; 28 | font-size: 0.625rem; 29 | font-family: "Roboto", sans-serif; 30 | 31 | &::placeholder { 32 | font-family: "Roboto", sans-serif; 33 | font-size: 0.625rem; 34 | } 35 | 36 | @media (min-width: 769px) { 37 | font-size: 1.625rem; 38 | padding: 1.25rem 1.875rem 1.25rem 1.25rem; 39 | 40 | &::placeholder { 41 | font-size: 1.625rem; 42 | } 43 | } 44 | } 45 | 46 | .searchIcon { 47 | height: 0.75rem; 48 | width: 0.75rem; 49 | 50 | @media (min-width: 769px) { 51 | height: 2rem; 52 | width: 2rem; 53 | } 54 | } 55 | 56 | .noStyleButton { 57 | background: none; 58 | color: inherit; 59 | border: none; 60 | padding: 0; 61 | font: inherit; 62 | cursor: pointer; 63 | outline: inherit; 64 | } 65 | 66 | .searchIconWrapper { 67 | position: absolute; 68 | right: 0.5rem; 69 | top: 50%; 70 | transform: translateY(-50%); 71 | 72 | @media (min-width: 769px) { 73 | right: 1.875rem; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/components/InfoCard/InfoCard.js: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import PropTypes from "prop-types"; // ES6 3 | import { useContext } from "react"; 4 | import { CITIES } from "../../lib/city"; 5 | import { TypeDataContext } from "../../lib/typeDataContext"; 6 | import styles from "./InfoCard.module.scss"; 7 | import { useTranslation } from "next-i18next"; 8 | 9 | const InfoCard = ({ item, districtMap, styleName }) => { 10 | const { data: typeData } = useContext(TypeDataContext); 11 | const { t } = useTranslation(); 12 | 13 | const cityName = CITIES?.[item.cityId]?.key; 14 | const districtName = districtMap?.get(item.districtId); 15 | 16 | const googleMapsLink = `https://www.google.com/maps/dir//${item.latitude},${item.longitude}`; 17 | 18 | const typeName = typeData?.find((type) => type.id === item.typeId)?.name; 19 | console.log(typeName, "type name"); 20 | return ( 21 |
22 |
23 | 24 | {typeName === "Hastane" 25 | ? t("common:hospitalBtn") 26 | : typeName === "Eczane" 27 | ? t("common:pharmacyBtn") 28 | : typeName === "Veteriner" 29 | ? t("common:vetBtn") 30 | : typeName === "Psikolojik Destek" 31 | ? t("common:psychologistBtn") 32 | : "" ?? "-"} 33 | 34 |
35 |
36 | {item.name} 37 | 38 | {item.phone && {item.phone}} 39 | 40 |
41 |
42 |
43 | {cityName && ( 44 | 45 | 46 | {cityName} | {districtName} 47 | 48 | 49 | )} 50 |
51 | {item?.address ?? "-"} 52 | {item?.additionalAddressDetails !== "" && ( 53 | {item.additionalAddressDetails} 54 | )} 55 |
56 |
57 |
58 | ); 59 | }; 60 | 61 | InfoCard.propTypes = { 62 | item: PropTypes.object.isRequired, 63 | districtMap: PropTypes.object.isRequired, 64 | styleName: PropTypes.string, 65 | }; 66 | 67 | export default InfoCard; 68 | -------------------------------------------------------------------------------- /src/components/InfoCard/InfoCard.module.scss: -------------------------------------------------------------------------------- 1 | .cardWrapper { 2 | box-sizing: border-box; 3 | margin: 0; 4 | background-color: white; 5 | border-radius: 10px; 6 | padding: 15px; 7 | min-width: 320px; 8 | margin: auto; 9 | width: 100%; 10 | height: 100%; 11 | 12 | .cardHeader { 13 | display: inline-block; 14 | padding-bottom: 5px; 15 | 16 | .cardHeaderTitle { 17 | font-family: "'Roboto', sans-serif"; 18 | font-style: normal; 19 | font-weight: 700; 20 | font-size: calc(10px + 0.390625vw); 21 | vertical-align: middle; 22 | padding-left: 5px; 23 | padding-bottom: 5px; 24 | 25 | &::before { 26 | vertical-align: middle; 27 | display: inline-block; 28 | width: calc(12px + 0.390625vw); 29 | height: calc(15px + 0.390625vw); 30 | align-items: center; 31 | margin-right: 3px; 32 | } 33 | 34 | &:global(.hastane) { 35 | color: #4bd80e; 36 | &::before { 37 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 137 138' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M41.0278 82.4009H50.1451V91.5182H41.0278V82.4009Z' fill='%238CF134'/%3E%3Cpath d='M63.821 82.4009H72.9383V91.5182H63.821V82.4009Z' fill='%238CF134'/%3E%3Cpath d='M86.6143 82.4009H95.7316V91.5182H86.6143V82.4009Z' fill='%238CF134'/%3E%3Cpath d='M120.806 127.987V20.8612H100.29V0.345215H36.4692V20.8612H15.9573V127.991H0V137.109H136.76V127.991L120.806 127.987ZM45.5865 9.46252H91.173V55.049H45.5865V9.46252ZM111.689 127.987H72.9384V109.753H63.8211V127.987H25.0746V29.9785H36.4733V64.1704H100.294V29.9785H111.693L111.689 127.987Z' fill='%238CF134'/%3E%3Cpath d='M72.9385 18.5801H63.8212V27.6974H54.7039V36.8147H63.8212V45.932H72.9385V36.8147H82.0558V27.6974H72.9385V18.5801Z' fill='%238CF134'/%3E%3C/svg%3E"); 38 | } 39 | } 40 | &:global(.eczane) { 41 | color: #f83b3b; 42 | &::before { 43 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 144 138' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M76.5025 11.3177C91.745 -3.31392 116.456 -3.31205 131.696 11.3219C146.936 25.9558 146.934 49.6803 131.692 64.3119L67.2963 126.136C52.0538 140.768 27.3428 140.766 12.1026 126.132C-3.13748 111.498 -3.13553 87.7738 12.107 73.1422L76.5025 11.3177ZM122.49 55.4775L94.8975 81.9766L58.0988 46.6472L85.7 20.1563C95.859 10.3995 112.333 10.3976 122.495 20.1516C132.657 29.9056 132.659 45.7218 122.499 55.4781L122.49 55.4775Z' fill='%23F83B3B'/%3E%3C/svg%3E"); 44 | } 45 | } 46 | &:global(.veteriner) { 47 | color: #fc6868; 48 | &::before { 49 | height: calc(12px + 0.390625vw); 50 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15.75' height='13.251' viewBox='0 0 15.75 13.251'%3E%3Cg id='Group_10313' data-name='Group 10313' transform='translate(-4958.003 1985.642)'%3E%3Cg id='paw-sharp' transform='translate(4958.003 -1985.642)'%3E%3Cpath id='Path_338' data-name='Path 338' d='M16.929,18.909a3.257,3.257,0,0,0-1.611-1.6,3.847,3.847,0,0,1-1.449-1.242c-.962-1.6-1.491-2.57-3.068-2.57s-2.107.968-3.072,2.57a3.852,3.852,0,0,1-1.452,1.245,3.264,3.264,0,0,0-1.611,1.594,2.422,2.422,0,0,0-.168.9,2.343,2.343,0,0,0,2.245,2.353c1.179,0,2.734-.578,4.061-.578s2.86.578,4.054.578A2.329,2.329,0,0,0,17.1,19.81a2.429,2.429,0,0,0-.171-.9Z' transform='translate(-2.924 -8.913)' fill='%23ff6464'/%3E%3Cpath id='Path_339' data-name='Path 339' d='M4.8,12.418a2.1,2.1,0,0,1-1.837,2.293,2.1,2.1,0,0,1-1.838-2.294,2.1,2.1,0,0,1,1.838-2.293A2.1,2.1,0,0,1,4.8,12.418Z' transform='translate(-1.125 -7.067)' fill='%23ff6464'/%3E%3Cpath id='Path_340' data-name='Path 340' d='M12.675,5.668a2.1,2.1,0,0,1-1.837,2.293A2.1,2.1,0,0,1,9,5.668a2.1,2.1,0,0,1,1.838-2.293,2.1,2.1,0,0,1,1.838,2.294Z' transform='translate(-5.325 -3.374)' fill='%23ff6464'/%3E%3Cpath id='Path_341' data-name='Path 341' d='M22.8,5.668a2.1,2.1,0,0,1-1.837,2.293,2.1,2.1,0,0,1-1.838-2.294,2.1,2.1,0,0,1,1.838-2.293A2.1,2.1,0,0,1,22.8,5.668Z' transform='translate(-10.725 -3.374)' fill='%23ff6464'/%3E%3Cpath id='Path_342' data-name='Path 342' d='M30.675,12.418a2.1,2.1,0,0,1-1.837,2.293A2.1,2.1,0,0,1,27,12.418a2.1,2.1,0,0,1,1.838-2.293,2.1,2.1,0,0,1,1.838,2.294Z' transform='translate(-14.925 -7.067)' fill='%23ff6464'/%3E%3C/g%3E%3Cpath id='plus' d='M4.667,1.956v.618a.294.294,0,0,1-.093.219.312.312,0,0,1-.225.09H2.97V4.221a.294.294,0,0,1-.093.219.312.312,0,0,1-.225.09H2.015a.312.312,0,0,1-.225-.09A.294.294,0,0,1,1.7,4.221V2.883H.318a.312.312,0,0,1-.225-.09A.293.293,0,0,1,0,2.574V1.956a.294.294,0,0,1,.093-.219.312.312,0,0,1,.225-.09H1.7V.309A.294.294,0,0,1,1.79.09.312.312,0,0,1,2.015,0h.636a.312.312,0,0,1,.225.09A.294.294,0,0,1,2.97.309V1.647H4.349a.312.312,0,0,1,.225.09.294.294,0,0,1,.093.219Z' transform='translate(4963.604 -1978.705)' fill='%23fff'/%3E%3C/g%3E%3C/svg%3E"); 51 | } 52 | } 53 | &:global(.psikolog) { 54 | color: #9b67c6; 55 | &::before { 56 | height: calc(15px + 0.390625vw); 57 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 129 138' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.03403 137C12.5354 137.061 113.033 137 119.534 137C126.035 137 128.031 131 128.031 121.5C128.031 112 110.529 79.5014 65.0312 79.5C19.534 79.4986 -0.953721 107.233 0.0340304 121.5C1.02178 135.767 3.53267 136.939 8.03403 137Z' fill='%239B67C6'/%3E%3Cpath d='M63.5312 68C82.3089 68 97.5312 52.7777 97.5312 34C97.5312 15.2223 82.3089 0 63.5312 0C44.7535 0 29.5312 15.2223 29.5312 34C29.5312 52.7777 44.7535 68 63.5312 68Z' fill='%239B67C6'/%3E%3Cpath d='M68.7659 20H59.6486V29.1173H50.5312V38.2346H59.6486V47.3519H68.7659V38.2346H77.8832V29.1173H68.7659V20Z' fill='white'/%3E%3C/svg%3E"); 58 | } 59 | } 60 | &:global(.diyaliz) { 61 | color: #aa0000; 62 | &::before { 63 | height: calc(12px + 0.390625vw); 64 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 192 144' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M69.7267 67.9588C75.246 61.9166 78.4583 45.4597 76.774 33.2471C75.0897 21.0346 73.2499 3.99656 49.8663 3.03516C26.4828 2.07376 10.2442 20.8387 2.77793 58.3167C-4.68832 95.7946 3.07349 129.458 23.9197 136.096C44.7658 142.734 59.4761 136.747 66.5235 130.311C73.5708 123.875 81.0111 109.017 67.1641 86.2788C68.2555 84.6532 68.8261 83.5098 69.7267 80.815C79.8234 85.8104 82.6396 91.8655 83.1806 107.813C83.4706 121.052 82.6967 128.849 80.2976 143.167H88.6262C91.5249 129.874 92.624 122.166 93.4312 107.813C93.5601 95.6267 92.8167 89.615 89.5872 80.815C84.9316 71.5212 80.6911 68.5627 69.7267 67.9588Z' fill='%23AA0000'/%3E%3Cpath d='M122.273 67.9588C116.754 61.9166 113.542 45.4597 115.226 33.2471C116.91 21.0346 118.75 3.99656 142.134 3.03516C165.517 2.07376 181.756 20.8387 189.222 58.3167C196.688 95.7946 188.927 129.458 168.08 136.096C147.234 142.734 132.524 136.747 125.477 130.311C118.429 123.875 110.989 109.017 124.836 86.2788C123.744 84.6532 123.174 83.5098 122.273 80.815C112.177 85.8104 109.36 91.8655 108.819 107.813C108.529 121.052 109.303 128.849 111.702 143.167H103.374C100.475 129.874 99.376 122.166 98.5688 107.813C98.4399 95.6267 99.1833 89.615 102.413 80.815C107.068 71.5212 111.309 68.5627 122.273 67.9588Z' fill='%23AA0000'/%3E%3Cpath d='M96 37C103.732 37 110 30.7552 110 23.0531C110 20.4774 109.493 17.8165 108.042 15.8987L96 -2.31875e-06L83.9581 15.8987C82.6386 17.6408 82 20.72 82 23.0531C82 30.7552 88.2675 37 96 37Z' fill='%23AA0000'/%3E%3C/svg%3E"); 65 | } 66 | } 67 | } 68 | .cardHeaderIcon { 69 | width: 16px; 70 | height: 16px; 71 | vertical-align: middle; 72 | } 73 | } 74 | 75 | .cardOrgName { 76 | padding-bottom: 10px; 77 | 78 | a { 79 | font-family: Roboto, sans-serif; 80 | font-weight: 600; 81 | font-size: calc(15px + 0.390625vw); 82 | text-decoration: none; 83 | color: #182151; 84 | } 85 | 86 | .cardOrgPhone { 87 | display: block; 88 | padding-top: 10px; 89 | 90 | a { 91 | display: flex; 92 | color: #182151; 93 | text-decoration: none; 94 | align-items: center; 95 | font-size: calc(10px + 0.390625vw); 96 | font-weight: 400; 97 | 98 | &::before { 99 | vertical-align: middle; 100 | display: inline-block; 101 | width: calc(8px + 0.390625vw); 102 | align-items: center; 103 | margin-right: 2px; 104 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 22 22' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.02 18.3307L18.0657 21.2611C17.6298 21.7081 17.0518 21.86 16.489 21.8606C13.9997 21.7861 11.6467 20.5633 9.71496 19.3079C6.54357 17.0008 3.6335 14.1402 1.80773 10.683C1.10698 9.23323 0.285179 7.3836 0.363751 5.7656C0.370735 5.15681 0.534863 4.55967 0.963225 4.16739L3.91752 1.21484C4.53097 0.693354 5.12404 0.873197 5.51689 1.4814L7.89325 5.98793C8.14352 6.52163 7.99976 7.09375 7.62669 7.47555L6.53833 8.56334C6.4714 8.65529 6.42833 8.76006 6.42716 8.87413C6.84447 10.4898 8.1086 11.9786 9.22548 13.0035C10.3424 14.0284 11.5431 15.4165 13.1011 15.7454C13.2938 15.7989 13.5295 15.8181 13.6674 15.6901L14.9333 14.4027C15.3698 14.0721 16.0001 13.9103 16.4657 14.1809H16.4878L20.7744 16.7115C21.4035 17.1061 21.4693 17.8686 21.0188 18.3318L21.02 18.3307Z' fill='%23182151'/%3E%3C/svg%3E"); 105 | } 106 | } 107 | } 108 | } 109 | 110 | .cardOrgInfo { 111 | padding: 10px 0; 112 | 113 | .cardOrgLocation { 114 | a { 115 | display: flex; 116 | color: #182151; 117 | text-decoration: none; 118 | align-items: center; 119 | 120 | &::before { 121 | vertical-align: middle; 122 | display: inline-block; 123 | width: calc(8px + 0.390625vw); 124 | height: calc(15px + 0.390625vw); 125 | align-items: center; 126 | margin-right: 3px; 127 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 17 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.49093 0.822266C3.8879 0.822266 0.153442 4.18394 0.153442 8.32601C0.153442 14.996 8.49093 24.1672 8.49093 24.1672C8.49093 24.1672 16.8284 14.996 16.8284 8.32601C16.8284 4.18394 13.094 0.822266 8.49093 0.822266ZM8.49093 12.4948C6.64906 12.4948 5.15593 11.0016 5.15593 9.15975C5.15593 7.31789 6.64906 5.82476 8.49093 5.82476C10.3328 5.82476 11.8259 7.31789 11.8259 9.15975C11.8239 11.0008 10.3319 12.4927 8.49093 12.4948Z' fill='%23182151'/%3E%3C/svg%3E"); 128 | } 129 | } 130 | } 131 | 132 | .cardOrgAddress { 133 | padding-top: 10px; 134 | 135 | span { 136 | display: block; 137 | color: gray; 138 | padding-top: 10px; 139 | } 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/components/ListPage/ListPage.js: -------------------------------------------------------------------------------- 1 | import PropTypes from "prop-types"; // ES6 2 | import Block from "../../lib/Block/Block"; 3 | import InfoCard from "../InfoCard/InfoCard"; 4 | import styles from "./ListPage.module.scss"; 5 | 6 | const ListPage = ({ data, districtMap }) => { 7 | return ( 8 | 9 |
10 | {data?.length ? ( 11 |
12 | {data?.map((item) => ( 13 | 19 | ))} 20 |
21 | ) : ( 22 |

23 | Aranılan kriterlere uygun sonuç bulunamadı. 24 |

25 | )} 26 |
27 |
28 | ); 29 | }; 30 | 31 | ListPage.propTypes = { 32 | data: PropTypes.array.isRequired, 33 | districtMap: PropTypes.object.isRequired, 34 | }; 35 | 36 | export default ListPage; 37 | -------------------------------------------------------------------------------- /src/components/ListPage/ListPage.module.scss: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | font-family: "Roboto", sans-serif; 3 | padding-right: 0.5rem; 4 | height: 500px; 5 | overflow: auto; 6 | 7 | @media (min-width: 769px) { 8 | padding-right: 1rem; 9 | } 10 | 11 | &::-webkit-scrollbar { 12 | width: 10px; 13 | } 14 | 15 | /* Track */ 16 | &::-webkit-scrollbar-track { 17 | background: #888; 18 | border-radius: 1rem; 19 | } 20 | 21 | /* Handle */ 22 | &::-webkit-scrollbar-thumb { 23 | border-radius: 1rem; 24 | background: #f1f1f1; 25 | } 26 | 27 | /* Handle on hover */ 28 | &::-webkit-scrollbar-thumb:hover { 29 | background: #555; 30 | } 31 | } 32 | 33 | .flexWrapper { 34 | display: grid; 35 | gap: 1rem; 36 | grid-template-columns: 1fr; 37 | @media (min-width: 769px) { 38 | gap: 1.25rem; 39 | grid-template-columns: 1fr 1fr; 40 | } 41 | @media (min-width: 1200px) { 42 | gap: 1.875rem; 43 | grid-template-columns: 1fr 1fr 1fr; 44 | } 45 | } 46 | 47 | .notFoundText { 48 | margin: auto; 49 | text-align: center; 50 | color: #f1f1f1; 51 | font-family: "Roboto", sans-serif; 52 | font-size: 1.5rem; 53 | } 54 | -------------------------------------------------------------------------------- /src/components/MainViewContainer/MainViewContainer.module.scss: -------------------------------------------------------------------------------- 1 | .mainViewContainerPaper { 2 | color: rgba(0, 0, 0, 0.87); 3 | transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/MapMarkerCluster/MapMarkerCluster.js: -------------------------------------------------------------------------------- 1 | import propTypes from "prop-types"; 2 | import { Marker, Popup } from "react-leaflet"; 3 | import MarkerClusterGroup from "react-leaflet-markercluster"; 4 | import { getTypeIcons } from "../../utils/generalFunctions"; 5 | import InfoCard from "../InfoCard/InfoCard"; 6 | 7 | const MapMarkerCluster = ({ searchFilteredData, districtMap }) => { 8 | return ( 9 | 10 | {searchFilteredData?.map((station) => { 11 | return ( 12 | 17 | 18 | 24 | 25 | 26 | ); 27 | })} 28 | 29 | ); 30 | }; 31 | 32 | MapMarkerCluster.propTypes = { 33 | searchFilteredData: propTypes.array, 34 | districtMap: propTypes.object, 35 | }; 36 | 37 | export default MapMarkerCluster; 38 | -------------------------------------------------------------------------------- /src/components/MapMarkerCluster/MapMarkerCluster.module.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/components/MapMarkerCluster/MapMarkerCluster.module.scss -------------------------------------------------------------------------------- /src/components/MapPage/MapPage.js: -------------------------------------------------------------------------------- 1 | import L from "leaflet"; 2 | 3 | import propTypes from "prop-types"; 4 | import React, { useState } from "react"; 5 | import { MapContainer, TileLayer } from "react-leaflet"; 6 | import Block from "../../lib/Block/Block"; 7 | 8 | import DragIcon from "../DragIcon/DragIcon"; 9 | import FullScreenIcon from "../FullScreenIcon/FullScreenIcon"; 10 | import MapMarkerCluster from "../MapMarkerCluster/MapMarkerCluster"; 11 | import styles from "./MapPage.module.scss"; 12 | 13 | import "react-leaflet-fullscreen/dist/styles.css"; 14 | 15 | /* const MapMarkerCluster = dynamic( 16 | () => import("../MapMarkerCluster/MapMarkerCluster"), 17 | { 18 | loading: () =>

loading...

, 19 | ssr: false, 20 | } 21 | ); 22 | 23 | const DragIcon = dynamic(() => import("../DragIcon/DragIcon"), { 24 | loading: () =>

loading...

, 25 | ssr: false, 26 | }); 27 | 28 | const FullScreenIcon = dynamic( 29 | () => import("../FullScreenIcon/FullScreenIcon"), 30 | { 31 | loading: () =>

loading...

, 32 | ssr: false, 33 | } 34 | ); */ 35 | 36 | const ZOOM = 6; 37 | const MIN_ZOOM = 7; 38 | 39 | // bunu gelen datanin varyansina gore ayarlarsak efsane olur 40 | const LAT_BOUND_THRESHOLD = 4; 41 | const LONG_BOUND_THRESHOLD = 10; 42 | 43 | const MapPage = ({ 44 | searchFilteredData, 45 | districtMap, 46 | setMap, 47 | handleLock, 48 | centerLatLong, 49 | }) => { 50 | const [dragActive, setDragActive] = useState(true); 51 | 52 | const center = [ 53 | centerLatLong?.latitude ?? 40, 54 | centerLatLong?.longitude ?? 35, 55 | ]; 56 | 57 | const leftTopBound = [ 58 | centerLatLong?.latitude - LAT_BOUND_THRESHOLD, 59 | centerLatLong?.longitude - LONG_BOUND_THRESHOLD, 60 | ]; 61 | const rightBottomBound = [ 62 | centerLatLong?.latitude + LAT_BOUND_THRESHOLD, 63 | centerLatLong?.longitude + LONG_BOUND_THRESHOLD, 64 | ]; 65 | 66 | const toggleDragActive = () => { 67 | setDragActive((active) => !active); 68 | }; 69 | 70 | const onLockClick = () => { 71 | handleLock(); 72 | toggleDragActive(); 73 | }; 74 | 75 | return ( 76 | 77 |
78 | 89 | 90 | 91 | 92 | 97 | 101 | 102 |
103 |
104 | ); 105 | }; 106 | 107 | MapPage.propTypes = { 108 | searchFilteredData: propTypes.array, 109 | districtMap: propTypes.object, 110 | setMap: propTypes.func, 111 | handleLock: propTypes.func, 112 | centerLatLong: propTypes.object.isRequired, 113 | }; 114 | 115 | export default MapPage; 116 | -------------------------------------------------------------------------------- /src/components/MapPage/MapPage.module.scss: -------------------------------------------------------------------------------- 1 | .mainViewContainerMapContainer { 2 | display: flex; 3 | height: 500px; 4 | border-radius: 17px; 5 | position: relative; 6 | } 7 | 8 | .mapContainer { 9 | height: 100%; 10 | width: 100%; 11 | position: absolute; 12 | top: 0; 13 | left: 0; 14 | @media screen and (min-width: 769px) { 15 | border-radius: 15px; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/Others/Others.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "next-i18next"; 3 | 4 | import styles from "./Others.module.scss"; 5 | 6 | const Others = () => { 7 | const otherWebsites = [ 8 | { 9 | key: "afet-harita", 10 | link: "https://afetharita.com/", 11 | text: "Depremzedeleri aramak ve yardım etmek için kullandığımız site.", 12 | imgSrc: "/icons/afet-harita.svg", 13 | }, 14 | { 15 | key: "deprem-io", 16 | link: "https://deprem.io/", 17 | text: "Afetle ilgili çeşitli konularda bilgi almak için kullandığımız web sitesi.", 18 | imgSrc: "/icons/deprem-io.svg", 19 | }, 20 | { 21 | key: "deprem-yardim", 22 | link: "https://depremyardim.com/", 23 | text: "Depremzedelere erzak yardımı için kullandığımız site.", 24 | imgSrc: "/icons/deprem-yardim.svg", 25 | }, 26 | ]; 27 | 28 | const { t } = useTranslation(); 29 | 30 | return ( 31 |
32 |

{t("common:helperSites")}:

33 |
34 | {otherWebsites.map((website) => ( 35 |
36 | 37 | {website.key} 45 | 46 | {website.text} 47 |
48 | ))} 49 |
50 |
51 | ); 52 | }; 53 | 54 | export default Others; 55 | -------------------------------------------------------------------------------- /src/components/Others/Others.module.scss: -------------------------------------------------------------------------------- 1 | .otherWrapper { 2 | display: flex; 3 | position: relative; 4 | align-items: center; 5 | gap: 10px; 6 | } 7 | 8 | .otherTitle { 9 | font-family: "Roboto", sans-serif; 10 | text-align: center; 11 | color: white; 12 | font-size: 1.5rem; 13 | font-weight: 500; 14 | white-space: nowrap; 15 | display: none; 16 | 17 | @media (min-width: 769px) { 18 | display: block; 19 | } 20 | } 21 | 22 | .logoContainer { 23 | color: white; 24 | display: flex; 25 | justify-content: space-between; 26 | align-items: center; 27 | 28 | background: rgba(255, 255, 255, 0.22); 29 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); 30 | backdrop-filter: blur(5.5px); 31 | border-radius: 0.625rem; 32 | gap: 0.5rem; 33 | padding: 0.5rem; 34 | 35 | @media (min-width: 768px) { 36 | padding: 0.5rem 1rem; 37 | } 38 | } 39 | 40 | .logoImg { 41 | width: 3rem; 42 | border-radius: 50%; 43 | cursor: pointer; 44 | transition: all 0.3s ease-in-out; 45 | &:hover { 46 | transform: scale(1.2); 47 | } 48 | } 49 | 50 | .tooltip { 51 | position: relative; 52 | display: inline-block; 53 | border-bottom: 1px dotted black; 54 | .tooltiptext { 55 | position: absolute; 56 | visibility: hidden; 57 | width: 25rem; 58 | top: -5rem; 59 | left: 50%; 60 | transform: translateX(-50%); 61 | background-color: white; 62 | color: #000; 63 | border-radius: 6px; 64 | padding: 0.625rem; 65 | font-family: "Roboto", sans-serif; 66 | z-index: 1; 67 | box-shadow: rgba(0, 0, 0, 0.24) 0 3px 8px; 68 | } 69 | &:hover .tooltiptext { 70 | @media screen and (min-width: 769px) { 71 | visibility: visible; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/icons/afet-harita.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/afet-harita.webp -------------------------------------------------------------------------------- /src/icons/deprem-io.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/deprem-io.webp -------------------------------------------------------------------------------- /src/icons/deprem-yardim.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/deprem-yardim.webp -------------------------------------------------------------------------------- /src/icons/deprem_io.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/hospital-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/hospital-1.png -------------------------------------------------------------------------------- /src/icons/hospital-1.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/hospital-marker-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/hospital-marker-2.png -------------------------------------------------------------------------------- /src/icons/hospital-marker-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/hospital-marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/hospital-marker.png -------------------------------------------------------------------------------- /src/icons/hospital-marker.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/icons/pharmacy-marker-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/pharmacy-marker-2.png -------------------------------------------------------------------------------- /src/icons/pharmacy-marker-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/icons/pharmacy-marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/pharmacy-marker.png -------------------------------------------------------------------------------- /src/icons/pharmacy-marker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/icons/vet-marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/vet-marker.png -------------------------------------------------------------------------------- /src/icons/vet-marker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/icons/vet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acikyazilimagi/eczane-frontend/0d78a19ee7c94ca50221b3602f5c6878f0fc5d43/src/icons/vet.png -------------------------------------------------------------------------------- /src/icons/vet.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", 4 | "Droid Sans", "Helvetica Neue", sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | 5 | const rootElement = document.getElementById("root"); 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | rootElement 11 | ); 12 | -------------------------------------------------------------------------------- /src/lib/Block/Block.js: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import PropTypes from "prop-types"; // ES6 3 | import styles from "./Block.module.scss"; 4 | 5 | const Block = ({ children, styleName, zeroPaddingOnMobile }) => { 6 | return ( 7 |
13 | {children} 14 |
15 | ); 16 | }; 17 | 18 | Block.propTypes = { 19 | children: PropTypes.node.isRequired, 20 | styleName: PropTypes.string, 21 | zeroPaddingOnMobile: PropTypes.bool, 22 | }; 23 | 24 | export default Block; 25 | -------------------------------------------------------------------------------- /src/lib/Block/Block.module.scss: -------------------------------------------------------------------------------- 1 | .block { 2 | display: grid; 3 | grid-template-columns: minmax(5vw, calc((100% - 1290px) / 2)) minmax(0, 1fr) minmax( 4 | 5vw, 5 | calc((100% - 1290px) / 2) 6 | ); 7 | grid-template-areas: left center right; 8 | align-items: flex-start; 9 | 10 | &:before, 11 | &:after { 12 | content: ""; 13 | } 14 | } 15 | 16 | .zeroPadOnMobile { 17 | grid-template-columns: minmax(0, calc((100% - 1290px) / 2)) minmax(0, 1fr) minmax( 18 | 0, 19 | calc((100% - 1290px) / 2) 20 | ); 21 | @media screen and (min-width: 769px) { 22 | grid-template-columns: minmax(5vw, calc((100% - 1290px) / 2)) minmax(0, 1fr) minmax( 23 | 5vw, 24 | calc((100% - 1290px) / 2) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/lib/Icons.js: -------------------------------------------------------------------------------- 1 | import L from "leaflet"; 2 | 3 | const common = { 4 | iconSize: [32, 42], 5 | iconAnchor: [18, 22], 6 | shadowUrl: null, 7 | shadowSize: null, // size of the shadow 8 | shadowAnchor: null, // the same for the shadow 9 | }; 10 | export const hospitalIcon = L.icon({ 11 | ...common, 12 | iconUrl: 13 | "data:image/svg+xml,%3Csvg width='381' height='505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.2 0C85.149 0 0 85.162 0 190.2c0 35.125 6.882 71.413 26.603 97.567L190.2 504.583l163.597-216.816c17.927-23.758 26.603-65.75 26.603-97.567C380.4 85.163 295.251 0 190.2 0zm0 110.167c44.193 0 80.047 35.84 80.047 80.047 0 44.193-35.854 80.033-80.047 80.033s-80.047-35.84-80.047-80.047c0-44.207 35.854-80.033 80.047-80.033z' fill='%2375C44C'/%3E%3Ccircle cx='190' cy='192' r='130' fill='%23fff'/%3E%3Cpath d='M163.028 199.401h9.117v9.117h-9.117v-9.117zM185.821 199.401h9.118v9.117h-9.118v-9.117zM208.615 199.401h9.117v9.117h-9.117v-9.117z' fill='%2375C44C'/%3E%3Cpath d='M242.807 244.987V137.861h-20.516v-20.516h-63.822v20.516h-20.511v107.13H122v9.118h136.76v-9.118l-15.953-.004zm-75.22-118.524h45.586v45.586h-45.586v-45.586zm66.102 118.524h-38.75v-18.234h-9.118v18.234h-38.746v-98.009h11.399v34.192h63.821v-34.192h11.398l-.004 98.009z' fill='%2375C44C'/%3E%3Cpath d='M194.939 135.58h-9.118v9.117h-9.117v9.118h9.117v9.117h9.118v-9.117h9.117v-9.118h-9.117v-9.117z' fill='%2375C44C'/%3E%3C/svg%3E", 14 | }); 15 | 16 | export const hospitalIcon2 = L.icon({ 17 | ...common, 18 | iconUrl: 19 | "data:image/svg+xml,%3Csvg width='381' height='505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.2 0C85.149 0 0 85.162 0 190.2c0 35.125 6.882 71.413 26.603 97.567L190.2 504.583l163.597-216.816c17.927-23.758 26.603-65.75 26.603-97.567C380.4 85.163 295.251 0 190.2 0zm0 110.167c44.193 0 80.047 35.84 80.047 80.047 0 44.193-35.854 80.033-80.047 80.033s-80.047-35.84-80.047-80.047c0-44.207 35.854-80.033 80.047-80.033z' fill='%23407EC2'/%3E%3Ccircle cx='190' cy='192' r='130' fill='%23fff'/%3E%3Cpath d='m242.807 237.988-9.118-107.127h-11.398v-20.516h-63.822v20.516h-12.932l-7.579 107.131H122v9.117h136.76v-9.117l-15.953-.004zm-75.22-118.525h45.586v45.586h-45.586v-45.586zm66.102 118.525h-86.614l8.482-98.01h2.917v34.192h63.821v-34.192h2.907l8.487 98.01z' fill='%23407EC2'/%3E%3Cpath d='M194.939 128.58h-9.118v9.117h-9.117v9.118h9.117v9.117h9.118v-9.117h9.117v-9.118h-9.117v-9.117z' fill='%23407EC2'/%3E%3C/svg%3E", 20 | }); 21 | 22 | export const pharmacyIcon = L.icon({ 23 | ...common, 24 | iconUrl: 25 | "data:image/svg+xml,%3Csvg width='381' height='505' viewBox='0 0 381 505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.2 0C85.1485 0 0 85.1625 0 190.2C0 225.325 6.88196 261.613 26.6028 287.767L190.2 504.583L353.797 287.767C371.724 264.009 380.4 222.017 380.4 190.2C380.4 85.1625 295.251 0 190.2 0ZM190.2 110.167C234.393 110.167 270.247 146.007 270.247 190.214C270.247 234.407 234.393 270.247 190.2 270.247C146.007 270.247 110.153 234.407 110.153 190.2C110.153 145.993 146.007 110.167 190.2 110.167Z' fill='%23F83B3B'/%3E%3Cpath d='M320 192C320 263.797 261.797 322 190 322C118.203 322 60 263.797 60 192C60 120.203 118.203 62 190 62C261.797 62 320 120.203 320 192Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M194.803 134.591C210.046 119.959 234.757 119.961 249.997 134.595C265.237 149.229 265.235 172.953 249.992 187.585L185.597 249.409C170.354 264.041 145.643 264.039 130.403 249.405C115.163 234.771 115.165 211.047 130.408 196.415L194.803 134.591ZM240.791 178.75L213.198 205.25L176.399 169.92L204.001 143.429C214.16 133.672 230.633 133.671 240.796 143.425C250.958 153.179 250.959 168.995 240.8 178.751L240.791 178.75Z' fill='%23F83B3B'/%3E%3C/svg%3E", //pharmacyIconSvg, 26 | }); 27 | 28 | export const pharmacyIcon2 = L.icon({ 29 | ...common, 30 | iconUrl: 31 | "data:image/svg+xml,%3Csvg width='381' height='505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.2 0C85.149 0 0 85.162 0 190.2c0 35.125 6.882 71.413 26.603 97.567L190.2 504.583l163.597-216.816c17.927-23.758 26.603-65.75 26.603-97.567C380.4 85.163 295.251 0 190.2 0zm0 110.167c44.193 0 80.047 35.84 80.047 80.047 0 44.193-35.854 80.033-80.047 80.033s-80.047-35.84-80.047-80.047c0-44.207 35.854-80.033 80.047-80.033z' fill='%23F79D25'/%3E%3Cpath d='M190 322c71.797 0 130-58.203 130-130S261.797 62 190 62 60 120.203 60 192s58.203 130 130 130z' fill='%23fff'/%3E%3Cpath d='m285.588 172.413-55.27-19.875-23.167-29.026a21.448 21.448 0 0 0-16.595-7.875h-57.202a21.451 21.451 0 0 0-17.663 9.438l-19.379 28.601a35.752 35.752 0 0 0-6.216 19.951v56.414a7.15 7.15 0 0 0 7.15 7.15h15.305a28.601 28.601 0 0 0 55.2 0h44.904a28.601 28.601 0 0 0 55.2 0h15.299a7.15 7.15 0 0 0 7.15-7.15v-50.91a7.15 7.15 0 0 0-4.722-6.718h.006zm-145.44 71.929c-7.898 0-14.3-6.403-14.3-14.301 0-7.898 6.402-14.3 14.3-14.3 7.898 0 14.301 6.402 14.301 14.3 0 7.898-6.403 14.301-14.301 14.301zm100.104 0c-7.898 0-14.301-6.403-14.301-14.301 0-7.898 6.403-14.3 14.301-14.3 7.898 0 14.301 6.402 14.301 14.3 0 7.898-6.403 14.301-14.301 14.301zm35.751-21.451h-8.148a28.601 28.601 0 0 0-55.2 0h-44.904a28.601 28.601 0 0 0-55.2 0h-8.154v-49.264a21.445 21.445 0 0 1 3.718-12.082l19.379-28.601a7.146 7.146 0 0 1 5.936-3h57.202a7.148 7.148 0 0 1 5.504 2.574l24.311 30.533a7.797 7.797 0 0 0 3.146 2.288l52.41 18.794v38.758z' fill='%23F79D25'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M160.883 142.909c6.661-6.394 17.461-6.394 24.122.002 6.661 6.396 6.66 16.765-.002 23.159l-28.144 27.021c-6.662 6.394-17.462 6.394-24.122-.002-6.661-6.396-6.66-16.765.002-23.159l28.144-27.021zm20.098 19.3-12.059 11.582-16.083-15.441 12.063-11.578c4.44-4.264 11.64-4.265 16.082-.002 4.441 4.263 4.442 11.176.001 15.44l-.004-.001z' fill='%23F79D25'/%3E%3C/svg%3E", 32 | }); 33 | 34 | export const vetIcon = L.icon({ 35 | ...common, 36 | iconUrl: 37 | "data:image/svg+xml,%3Csvg width='381' height='505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.2 0C85.149 0 0 85.162 0 190.2c0 35.125 6.882 71.413 26.603 97.567L190.2 504.583l163.597-216.816c17.927-23.758 26.603-65.75 26.603-97.567C380.4 85.163 295.251 0 190.2 0zm0 110.167c44.193 0 80.047 35.84 80.047 80.047 0 44.193-35.854 80.033-80.047 80.033s-80.047-35.84-80.047-80.047c0-44.207 35.854-80.033 80.047-80.033z' fill='%23FF6464'/%3E%3Ccircle cx='190' cy='192' r='130' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M164.015 169c4.745-8.89 14.599-15 25.985-15 12.84 0 23.731 7.77 27.546 18.534 2.841 4.738 8.224 13.114 13.454 17.966 3.427 3.179 8.637 6.561 12.386 8.828C254.192 202.855 262 213.016 262 225c0 14.912-12.088 27-27 27-3.126 0-6.129-.531-8.921-1.509-7.492-1.85-24.156-5.59-36.079-5.491-15.055.125-38 6.5-38 6.5l-.155-.375c-2.186.571-4.48.875-6.845.875-14.912 0-27-12.088-27-27 0-11.583 7.294-21.463 17.54-25.296 4.604-2.729 12.06-7.507 16.46-12.204 5.888-6.284 12-18.5 12-18.5h.015z' fill='%23FF6464'/%3E%3Cellipse cx='122' cy='162' rx='21' ry='26' fill='%23FF6464'/%3E%3Cellipse cx='164' cy='128' rx='21' ry='26' fill='%23FF6464'/%3E%3Cellipse cx='217' cy='128' rx='21' ry='26' fill='%23FF6464'/%3E%3Cellipse cx='258' cy='162' rx='21' ry='26' fill='%23FF6464'/%3E%3Cpath d='M196 189h-11v11h-11v11h11v11h11v-11h11v-11h-11v-11z' fill='%23fff'/%3E%3C/svg%3E", 38 | }); 39 | 40 | export const psikologIcon = L.icon({ 41 | ...common, 42 | iconUrl: 43 | "data:image/svg+xml,%3Csvg width='381' height='505' viewBox='0 0 381 505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.533 0C85.4815 0 0.333008 85.1625 0.333008 190.2C0.333008 225.325 7.21497 261.613 26.9358 287.767L190.533 504.583L354.13 287.767C372.057 264.009 380.733 222.017 380.733 190.2C380.733 85.1625 295.584 0 190.533 0ZM190.533 110.167C234.726 110.167 270.58 146.007 270.58 190.214C270.58 234.407 234.726 270.247 190.533 270.247C146.34 270.247 110.486 234.407 110.486 190.2C110.486 145.993 146.34 110.167 190.533 110.167Z' fill='%239B67C6'/%3E%3Cpath d='M190 322C261.797 322 320 263.797 320 192C320 120.203 261.797 62 190 62C118.203 62 60 120.203 60 192C60 263.797 118.203 322 190 322Z' fill='white'/%3E%3Cpath d='M134.034 252C138.535 252.061 239.033 252 245.534 252C252.035 252 254.031 246 254.031 236.5C254.031 227 236.529 194.501 191.031 194.5C145.534 194.499 125.046 222.233 126.034 236.5C127.022 250.767 129.533 251.939 134.034 252Z' fill='%239B67C6'/%3E%3Cpath d='M189.531 183C208.309 183 223.531 167.778 223.531 149C223.531 130.222 208.309 115 189.531 115C170.753 115 155.531 130.222 155.531 149C155.531 167.778 170.753 183 189.531 183Z' fill='%239B67C6'/%3E%3Cpath d='M194.766 135H185.649V144.117H176.531V153.235H185.649V162.352H194.766V153.235H203.883V144.117H194.766V135Z' fill='white'/%3E%3C/svg%3E", 44 | }); 45 | 46 | export const diyalizIcon = L.icon({ 47 | ...common, 48 | iconUrl: 49 | "data:image/svg+xml,%3Csvg width='381' height='505' viewBox='0 0 381 505' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M190.2 0C85.1485 0 0 85.1625 0 190.2C0 225.325 6.88196 261.613 26.6028 287.767L190.2 504.583L353.797 287.767C371.724 264.009 380.4 222.017 380.4 190.2C380.4 85.1625 295.251 0 190.2 0ZM190.2 110.167C234.393 110.167 270.247 146.007 270.247 190.214C270.247 234.407 234.393 270.247 190.2 270.247C146.007 270.247 110.153 234.407 110.153 190.2C110.153 145.993 146.007 110.167 190.2 110.167Z' fill='%23AA0000'/%3E%3Cpath d='M190 321C261.797 321 320 262.797 320 191C320 119.203 261.797 61 190 61C118.203 61 60 119.203 60 191C60 262.797 118.203 321 190 321Z' fill='white'/%3E%3Cpath d='M159.727 185.959C165.246 179.917 168.458 163.46 166.774 151.247C165.09 139.035 163.25 121.997 139.866 121.035C116.483 120.074 100.244 138.839 92.7779 176.317C85.3117 213.795 93.0735 247.458 113.92 254.096C134.766 260.734 149.476 254.747 156.523 248.311C163.571 241.875 171.011 227.017 157.164 204.279C158.256 202.653 158.826 201.51 159.727 198.815C169.823 203.81 172.64 209.865 173.181 225.813C173.471 239.052 172.697 246.849 170.298 261.167H178.626C181.525 247.874 182.624 240.166 183.431 225.813C183.56 213.627 182.817 207.615 179.587 198.815C174.932 189.521 170.691 186.563 159.727 185.959Z' fill='%23AA0000'/%3E%3Cpath d='M212.273 185.959C206.754 179.917 203.542 163.46 205.226 151.247C206.91 139.035 208.75 121.997 232.134 121.035C255.517 120.074 271.756 138.839 279.222 176.317C286.688 213.795 278.927 247.458 258.08 254.096C237.234 260.734 222.524 254.747 215.477 248.311C208.429 241.875 200.989 227.017 214.836 204.279C213.744 202.653 213.174 201.51 212.273 198.815C202.177 203.81 199.36 209.865 198.819 225.813C198.529 239.052 199.303 246.849 201.702 261.167H193.374C190.475 247.874 189.376 240.166 188.569 225.813C188.44 213.627 189.183 207.615 192.413 198.815C197.068 189.521 201.309 186.563 212.273 185.959Z' fill='%23AA0000'/%3E%3Cpath d='M186 155C193.732 155 200 148.755 200 141.053C200 138.477 199.493 135.817 198.042 133.899L186 118L173.958 133.899C172.639 135.641 172 138.72 172 141.053C172 148.755 178.268 155 186 155Z' fill='%23AA0000'/%3E%3C/svg%3E", 50 | }); 51 | -------------------------------------------------------------------------------- /src/lib/Spacer.js: -------------------------------------------------------------------------------- 1 | import PropTypes from "prop-types"; // ES6 2 | 3 | export const Spacer = ({ size }) =>
; 4 | 5 | Spacer.propTypes = { 6 | size: PropTypes.number.isRequired, 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/city.js: -------------------------------------------------------------------------------- 1 | export const CITIES = { 2 | 1: { 3 | id: 1, 4 | key: "Adana", 5 | }, 6 | 2: { 7 | id: 2, 8 | key: "Adiyaman", 9 | }, 10 | 21: { 11 | id: 21, 12 | key: "Diyarbakır", 13 | }, 14 | 27: { 15 | id: 27, 16 | key: "Gaziantep", 17 | }, 18 | 31: { 19 | id: 31, 20 | key: "Hatay", 21 | }, 22 | 44: { 23 | id: 44, 24 | key: "Malatya", 25 | }, 26 | 46: { 27 | id: 46, 28 | key: "Kahramanmaraş", 29 | }, 30 | 63: { 31 | id: 63, 32 | key: "Şanlıurfa", 33 | }, 34 | 79: { 35 | id: 79, 36 | key: "Kilis", 37 | }, 38 | 80: { 39 | id: 80, 40 | key: "Osmaniye", 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /src/lib/cityCenters.js: -------------------------------------------------------------------------------- 1 | const centers = { 2 | Adana: { 3 | id: 1, 4 | lat: 36.9914, 5 | lng: 35.3308, 6 | }, 7 | Adıyaman: { 8 | id: 2, 9 | lat: 37.7636, 10 | lng: 38.2773, 11 | }, 12 | Afyonkarahisar: { 13 | id: 3, 14 | lat: 38.7507, 15 | lng: 30.5567, 16 | }, 17 | Ağrı: { 18 | id: 4, 19 | lat: 39.7191, 20 | lng: 43.0503, 21 | }, 22 | Amasya: { 23 | id: 5, 24 | lat: 40.6499, 25 | lng: 35.8353, 26 | }, 27 | Ankara: { 28 | id: 6, 29 | lat: 39.9208, 30 | lng: 32.8541, 31 | }, 32 | Antalya: { 33 | id: 7, 34 | lat: 36.8841, 35 | lng: 30.7056, 36 | }, 37 | Artvin: { 38 | id: 8, 39 | lat: 41.1828, 40 | lng: 41.8183, 41 | }, 42 | Aydın: { 43 | id: 9, 44 | lat: 37.8564, 45 | lng: 27.8416, 46 | }, 47 | Balıkesir: { 48 | id: 10, 49 | lat: 39.6484, 50 | lng: 27.8826, 51 | }, 52 | Bilecik: { 53 | id: 11, 54 | lat: 40.1451, 55 | lng: 29.9799, 56 | }, 57 | Bingöl: { 58 | id: 12, 59 | lat: 38.8852, 60 | lng: 40.4988, 61 | }, 62 | Bitlis: { 63 | id: 13, 64 | lat: 38.3952, 65 | lng: 42.1255, 66 | }, 67 | Bolu: { 68 | id: 14, 69 | lat: 40.7356, 70 | lng: 31.6012, 71 | }, 72 | Burdur: { 73 | id: 15, 74 | lat: 37.7192, 75 | lng: 30.2903, 76 | }, 77 | Bursa: { 78 | id: 16, 79 | lat: 40.1824, 80 | lng: 29.0651, 81 | }, 82 | Çanakkale: { 83 | id: 17, 84 | lat: 40.1549, 85 | lng: 26.4142, 86 | }, 87 | Çankırı: { 88 | id: 18, 89 | lat: 40.6012, 90 | lng: 33.6137, 91 | }, 92 | Çorum: { 93 | id: 19, 94 | lat: 40.5503, 95 | lng: 34.9553, 96 | }, 97 | Denizli: { 98 | id: 20, 99 | lat: 37.7765, 100 | lng: 29.0864, 101 | }, 102 | Diyarbakır: { 103 | id: 21, 104 | lat: 37.9138, 105 | lng: 40.2306, 106 | }, 107 | Edirne: { 108 | id: 22, 109 | lat: 41.6764, 110 | lng: 26.5553, 111 | }, 112 | Elazığ: { 113 | id: 23, 114 | lat: 38.674, 115 | lng: 39.2232, 116 | }, 117 | Erzincan: { 118 | id: 24, 119 | lat: 39.7507, 120 | lng: 39.4929, 121 | }, 122 | Erzurum: { 123 | id: 25, 124 | lat: 39.9085, 125 | lng: 41.2769, 126 | }, 127 | Eskişehir: { 128 | id: 26, 129 | lat: 39.7767, 130 | lng: 30.5206, 131 | }, 132 | Gaziantep: { 133 | id: 27, 134 | lat: 37.0594, 135 | lng: 37.3821, 136 | }, 137 | Giresun: { 138 | id: 28, 139 | lat: 40.9128, 140 | lng: 38.3895, 141 | }, 142 | Gümüşhane: { 143 | id: 29, 144 | lat: 40.4603, 145 | lng: 39.4817, 146 | }, 147 | Hakkari: { 148 | id: 30, 149 | lat: 37.5733, 150 | lng: 43.7408, 151 | }, 152 | Hatay: { 153 | id: 31, 154 | lat: 36.4012, 155 | lng: 36.349, 156 | }, 157 | Isparta: { 158 | id: 32, 159 | lat: 37.7648, 160 | lng: 30.5567, 161 | }, 162 | Mersin: { 163 | id: 33, 164 | lat: 36.7956, 165 | lng: 34.6328, 166 | }, 167 | İstanbul: { 168 | id: 34, 169 | lat: 41.0138, 170 | lng: 28.9497, 171 | }, 172 | İzmir: { 173 | id: 35, 174 | lat: 38.4189, 175 | lng: 27.1287, 176 | }, 177 | Kars: { 178 | id: 36, 179 | lat: 40.6088, 180 | lng: 43.0977, 181 | }, 182 | Kastamonu: { 183 | id: 37, 184 | lat: 41.3888, 185 | lng: 33.7825, 186 | }, 187 | Kayseri: { 188 | id: 38, 189 | lat: 38.7312, 190 | lng: 35.4784, 191 | }, 192 | Kırklareli: { 193 | id: 39, 194 | lat: 41.7373, 195 | lng: 27.2264, 196 | }, 197 | Kırşehir: { 198 | id: 40, 199 | lat: 39.1428, 200 | lng: 34.1706, 201 | }, 202 | Kocaeli: { 203 | id: 41, 204 | lat: 40.8531, 205 | lng: 29.8815, 206 | }, 207 | Konya: { 208 | id: 42, 209 | lat: 37.8715, 210 | lng: 32.4849, 211 | }, 212 | Kütahya: { 213 | id: 43, 214 | lat: 39.4167, 215 | lng: 29.9833, 216 | }, 217 | Malatya: { 218 | id: 44, 219 | lat: 38.3557, 220 | lng: 38.3096, 221 | }, 222 | Manisa: { 223 | id: 45, 224 | lat: 38.6191, 225 | lng: 27.4289, 226 | }, 227 | Kahramanmaraş: { 228 | id: 46, 229 | lat: 37.5853, 230 | lng: 36.9376, 231 | }, 232 | Mardin: { 233 | id: 47, 234 | lat: 37.3117, 235 | lng: 40.7436, 236 | }, 237 | Muğla: { 238 | id: 48, 239 | lat: 37.2164, 240 | lng: 28.3636, 241 | }, 242 | Muş: { 243 | id: 49, 244 | lat: 38.7478, 245 | lng: 41.6612, 246 | }, 247 | Nevşehir: { 248 | id: 50, 249 | lat: 38.6244, 250 | lng: 34.7239, 251 | }, 252 | Niğde: { 253 | id: 51, 254 | lat: 37.9667, 255 | lng: 34.6833, 256 | }, 257 | Ordu: { 258 | id: 52, 259 | lat: 40.9833, 260 | lng: 37.8833, 261 | }, 262 | Rize: { 263 | id: 53, 264 | lat: 41.0204, 265 | lng: 40.5237, 266 | }, 267 | Sakarya: { 268 | id: 54, 269 | lat: 40.7767, 270 | lng: 30.3789, 271 | }, 272 | Samsun: { 273 | id: 55, 274 | lat: 41.2794, 275 | lng: 36.3433, 276 | }, 277 | Siirt: { 278 | id: 56, 279 | lat: 37.9442, 280 | lng: 41.9325, 281 | }, 282 | Sinop: { 283 | id: 57, 284 | lat: 42.0231, 285 | lng: 35.1533, 286 | }, 287 | Sivas: { 288 | id: 58, 289 | lat: 39.7453, 290 | lng: 37.0144, 291 | }, 292 | Tekirdağ: { 293 | id: 59, 294 | lat: 40.9833, 295 | lng: 27.5167, 296 | }, 297 | Tokat: { 298 | id: 60, 299 | lat: 40.3167, 300 | lng: 36.55, 301 | }, 302 | Trabzon: { 303 | id: 61, 304 | lat: 41.0053, 305 | lng: 39.7267, 306 | }, 307 | Tunceli: { 308 | id: 62, 309 | lat: 39.1053, 310 | lng: 39.5303, 311 | }, 312 | Şanlıurfa: { 313 | id: 63, 314 | lat: 37.1591, 315 | lng: 38.7968, 316 | }, 317 | Uşak: { 318 | id: 64, 319 | lat: 38.6825, 320 | lng: 29.4089, 321 | }, 322 | Van: { 323 | id: 65, 324 | lat: 38.49, 325 | lng: 43.38, 326 | }, 327 | Yozgat: { 328 | id: 66, 329 | lat: 39.82, 330 | lng: 34.8042, 331 | }, 332 | Zonguldak: { 333 | id: 67, 334 | lat: 41.4567, 335 | lng: 31.7986, 336 | }, 337 | Aksaray: { 338 | id: 68, 339 | lat: 38.3667, 340 | lng: 34.0333, 341 | }, 342 | Bayburt: { 343 | id: 69, 344 | lat: 40.2556, 345 | lng: 40.2244, 346 | }, 347 | Karaman: { 348 | id: 70, 349 | lat: 37.175, 350 | lng: 33.2156, 351 | }, 352 | Kırıkkale: { 353 | id: 71, 354 | lat: 39.8467, 355 | lng: 33.5158, 356 | }, 357 | Batman: { 358 | id: 72, 359 | lat: 37.8819, 360 | lng: 41.1358, 361 | }, 362 | Şırnak: { 363 | id: 73, 364 | lat: 37.5167, 365 | lng: 42.4667, 366 | }, 367 | Bartın: { 368 | id: 74, 369 | lat: 41.6344, 370 | lng: 32.3372, 371 | }, 372 | Ardahan: { 373 | id: 75, 374 | lat: 41.1106, 375 | lng: 42.7025, 376 | }, 377 | Iğdır: { 378 | id: 76, 379 | lat: 39.9167, 380 | lng: 44.0333, 381 | }, 382 | Yalova: { 383 | id: 77, 384 | lat: 40.65, 385 | lng: 29.2667, 386 | }, 387 | Karabük: { 388 | id: 78, 389 | lat: 41.2, 390 | lng: 32.6333, 391 | }, 392 | Kilis: { 393 | id: 79, 394 | lat: 36.7167, 395 | lng: 37.1167, 396 | }, 397 | Osmaniye: { 398 | id: 80, 399 | lat: 37.0742, 400 | lng: 36.2469, 401 | }, 402 | Düzce: { 403 | id: 81, 404 | lat: 40.8431, 405 | lng: 31.1565, 406 | }, 407 | }; 408 | export default centers; 409 | -------------------------------------------------------------------------------- /src/lib/typeDataContext.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | export const TypeDataContext = React.createContext({}); 3 | -------------------------------------------------------------------------------- /src/styles/App.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap"); 2 | 3 | //pages 4 | @import "./Homepage.scss"; 5 | 6 | //components 7 | 8 | @import "../components/MainViewContainer/MainViewContainer.module.scss"; 9 | -------------------------------------------------------------------------------- /src/utils/calculateCenter.js: -------------------------------------------------------------------------------- 1 | export const calculateCenter = (fetchedData) => { 2 | const latlongsSum = fetchedData?.data?.reduce( 3 | (acc, curr) => { 4 | acc.latitude += curr.latitude; 5 | acc.longitude += curr.longitude; 6 | return acc; 7 | }, 8 | { latitude: 0, longitude: 0 } 9 | ); 10 | const len = fetchedData?.data?.length; 11 | const centerLatLong = { 12 | latitude: latlongsSum.latitude / len, 13 | longitude: latlongsSum.longitude / len, 14 | }; 15 | return centerLatLong; 16 | }; 17 | -------------------------------------------------------------------------------- /src/utils/constants.js: -------------------------------------------------------------------------------- 1 | export const SEARCH_AT = { 2 | HARITA: "harita", 3 | LISTE: "liste", 4 | }; 5 | 6 | export const HEPSI_ID = 0; 7 | 8 | export const LANGUAGE_KEY_LOCAL_STORAGE = "i18nextLng"; 9 | -------------------------------------------------------------------------------- /src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | export function debounce(func, delay) { 2 | let debounceTimer; 3 | return function () { 4 | const context = this; 5 | const args = arguments; 6 | clearTimeout(debounceTimer); 7 | debounceTimer = setTimeout(() => func.apply(context, args), delay); 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/generalFunctions.js: -------------------------------------------------------------------------------- 1 | import { 2 | diyalizIcon, 3 | hospitalIcon, 4 | pharmacyIcon, 5 | psikologIcon, 6 | vetIcon, 7 | } from "../lib/Icons"; 8 | import { HEPSI_ID } from "./constants"; 9 | 10 | // FIXME: This is a temporary solution. We should use a better way to get the icons. 11 | export const getTypeIcons = (type) => { 12 | switch (type) { 13 | case HEPSI_ID: 14 | return hospitalIcon; 15 | case 1: 16 | return pharmacyIcon; 17 | case 4: 18 | return vetIcon; 19 | case 3: 20 | return psikologIcon; 21 | case 5: 22 | return diyalizIcon; 23 | default: 24 | return hospitalIcon; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/utils/hooks.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { useEffect, useState } from "react"; 3 | import { 4 | largeThreshold, 5 | mobileThreshold, 6 | xLargeThreshold, 7 | xxxLargeThreshold, 8 | } from "../utils/styled"; 9 | import { debounce } from "./debounce"; 10 | 11 | export function useWindowSize(initial) { 12 | const [windowSize, setWindowSize] = useState({ 13 | width: undefined, 14 | height: undefined, 15 | isDesktop: initial?.isDesktop ?? undefined, 16 | isMobile: initial?.isMobile ?? undefined, 17 | isLarge: undefined, 18 | isXLarge: undefined, 19 | isLandscape: undefined, 20 | isTablet: undefined, 21 | isXXXLarge: undefined, 22 | }); 23 | 24 | useEffect(() => { 25 | function handleResize() { 26 | const isLarge = window.innerWidth > largeThreshold; 27 | const isDesktop = window.innerWidth > mobileThreshold; 28 | const isMobile = !isDesktop; 29 | 30 | setWindowSize({ 31 | width: window.innerWidth, 32 | height: window.innerHeight, 33 | isDesktop, 34 | isMobile, 35 | isLarge, 36 | isXLarge: window.innerWidth > xLargeThreshold, 37 | isLandscape: window.innerWidth > window.innerHeight, 38 | isTablet: !isLarge && isDesktop, 39 | isXXXLarge: window.innerWidth > xxxLargeThreshold, 40 | }); 41 | } 42 | 43 | const debouncedResize = debounce(handleResize, 50); 44 | window.addEventListener("resize", handleResize); 45 | handleResize(); 46 | return () => window.removeEventListener("resize", debouncedResize); 47 | }, []); 48 | 49 | return windowSize; 50 | } 51 | 52 | export function useFetch(url) { 53 | const [data, setData] = useState(null); 54 | const [loading, setLoading] = useState(false); 55 | const [error, setError] = useState(null); 56 | useEffect(() => { 57 | setLoading(true); 58 | axios 59 | .get(url) 60 | .then((response) => { 61 | setData(response?.data); 62 | }) 63 | .catch((err) => { 64 | setError(err); 65 | }) 66 | .finally(() => { 67 | setLoading(false); 68 | }); 69 | }, [url]); 70 | 71 | return { data, loading, error }; 72 | } 73 | 74 | export function getLocalStorage(key, initialValue) { 75 | if (typeof window === "undefined") { 76 | return initialValue; 77 | } 78 | try { 79 | const item = window.localStorage.getItem(key); 80 | const val = item ?? initialValue; 81 | return val; 82 | } catch (error) { 83 | return initialValue; 84 | } 85 | } 86 | 87 | export function useLocalStorage(key, initialValue) { 88 | const [storedValue, setStoredValue] = useState(() => { 89 | const val = getLocalStorage(key, initialValue); 90 | return val; 91 | }); 92 | 93 | const setValue = (value) => { 94 | try { 95 | setStoredValue(value); 96 | if (typeof window !== "undefined") { 97 | window.localStorage.setItem(key, value); 98 | } 99 | } catch (error) { 100 | console.error(error); 101 | } 102 | }; 103 | return [storedValue, setValue]; 104 | } 105 | -------------------------------------------------------------------------------- /src/utils/styled.js: -------------------------------------------------------------------------------- 1 | function getMediaQuery(size) { 2 | class MediaQuery { 3 | size = 0; 4 | min = ""; 5 | max = ""; 6 | gt = ""; 7 | 8 | constructor(size) { 9 | this.size = size; 10 | // IMPROVE: refactor gt alias to min - there's no need to have both min-width: size + 1 and min-width: size 11 | // min-width: size doesn't play well with max-width: size, as both rules are applied at the threshold 12 | this.min = `(min-width: ${this.size + 1}px)`; 13 | this.gt = `(min-width: ${this.size + 1}px)`; 14 | this.max = `(max-width: ${this.size}px)`; 15 | } 16 | toString() { 17 | return this.max; 18 | } 19 | css(css) { 20 | return { 21 | [`@media ${this.max}`]: css, 22 | }; 23 | } 24 | } 25 | 26 | return new MediaQuery(size); 27 | } 28 | 29 | export const mobileThreshold = 768; 30 | export const largeThreshold = 1024; 31 | export const xLargeThreshold = 1440; 32 | export const xxLargeThreshold = 1600; 33 | export const xxxLargeThreshold = 1920; 34 | export const BREAKPOINTS = { 35 | /** 320px */ 36 | XS: getMediaQuery(320), 37 | /** 425px */ 38 | SM: getMediaQuery(425), 39 | /** 768px */ 40 | MD: getMediaQuery(mobileThreshold), 41 | /** 1024px */ 42 | LG: getMediaQuery(largeThreshold), 43 | /** 1440px */ 44 | XL: getMediaQuery(xLargeThreshold), 45 | }; 46 | -------------------------------------------------------------------------------- /task-definition.json: -------------------------------------------------------------------------------- 1 | { 2 | "containerDefinitions": [ 3 | { 4 | "name": "container-name", 5 | "image": "nginx:latest", 6 | "cpu": 512, 7 | "memory": 1024, 8 | "portMappings": [ 9 | { 10 | "name": "container-name-80-tcp", 11 | "containerPort": 80, 12 | "hostPort": 80, 13 | "protocol": "tcp" 14 | } 15 | ], 16 | "essential": true, 17 | "environment": [], 18 | "mountPoints": [], 19 | "volumesFrom": [], 20 | "logConfiguration": { 21 | "logDriver": "awslogs", 22 | "options": { 23 | "awslogs-create-group": "true", 24 | "awslogs-group": "/ecs/eczane-front", 25 | "awslogs-region": "eu-central-1", 26 | "awslogs-stream-prefix": "ecs" 27 | } 28 | } 29 | } 30 | ], 31 | "family": "eczane-front-TD", 32 | "executionRoleArn": "arn:aws:iam::366354050833:role/ecsServiceRole", 33 | "networkMode": "awsvpc", 34 | "volumes": [], 35 | "placementConstraints": [], 36 | "cpu": "512", 37 | "memory": "1024", 38 | "tags": [] 39 | } --------------------------------------------------------------------------------