├── mobile ├── .gitattributes ├── assets │ ├── icon.png │ ├── splash.png │ ├── secure-payment.png │ └── splash-tablet.png ├── lang │ └── i18n.ts ├── services │ ├── axiosInstance.ts │ └── AgencyService.ts ├── components │ ├── AutocompleteDropdown-v4.3.1 │ │ ├── types │ │ │ └── global.d.ts │ │ ├── helpers.ts │ │ ├── useKeyboardHeight.ts │ │ ├── theme.tsx │ │ ├── NothingFound.tsx │ │ └── HOC │ │ │ └── withFadeAnimation.tsx │ ├── AutocompleteDropdown-v4 │ │ ├── types │ │ │ └── global.d.ts │ │ ├── helpers.ts │ │ ├── useKeyboardHeight.ts │ │ ├── theme.tsx │ │ ├── NothingFound.tsx │ │ └── HOC │ │ │ └── withFadeAnimation.tsx │ ├── Indicator.tsx │ ├── Error.tsx │ ├── AutocompleteDropdown-v2 │ │ ├── NothingFound.tsx │ │ └── HOC │ │ │ └── withFadeAnimation.tsx │ ├── Backdrop.tsx │ ├── Link.tsx │ ├── Checkbox.tsx │ └── NavigationWrapper.tsx ├── tsconfig.json ├── .env.example ├── utils │ ├── toastHelper.ts │ └── axiosHelper.ts ├── babel.config.js ├── eas.json ├── types │ └── env.d.ts ├── context │ └── GlobalContext.tsx ├── plugins │ └── usesCleartextTraffic.js └── metro.config.js ├── .husky └── pre-commit ├── admin ├── .stylelintrc.json ├── src │ ├── vite-env.d.ts │ ├── assets │ │ ├── css │ │ │ ├── search.css │ │ │ ├── index.css │ │ │ ├── error.css │ │ │ ├── progress.css │ │ │ ├── contact.css │ │ │ ├── booking-filter.css │ │ │ ├── property-scheduler-filter.css │ │ │ ├── tos.css │ │ │ ├── hidden.css │ │ │ ├── available.css │ │ │ ├── info-box.css │ │ │ ├── pager.css │ │ │ ├── contact-form.css │ │ │ ├── rental-term-filter.css │ │ │ ├── update-agency.css │ │ │ ├── availability-filter.css │ │ │ ├── property-type-filter.css │ │ │ ├── agency-badge.css │ │ │ ├── create-user.css │ │ │ ├── create-location.css │ │ │ ├── update-location.css │ │ │ ├── create-agency.css │ │ │ ├── create-country.css │ │ │ ├── change-password.css │ │ │ ├── about.css │ │ │ ├── forgot-password.css │ │ │ ├── update-country.css │ │ │ ├── update-user.css │ │ │ ├── reset-password.css │ │ │ ├── status-list.css │ │ │ ├── header.css │ │ │ ├── status-filter.css │ │ │ ├── create-booking.css │ │ │ └── country-list.css │ │ └── img │ │ │ └── property.png │ ├── types │ │ └── index.d.ts │ ├── config │ │ └── const.ts │ ├── components │ │ ├── scheduler │ │ │ ├── helpers │ │ │ │ └── constants.ts │ │ │ ├── hooks │ │ │ │ ├── useStore.ts │ │ │ │ ├── useSyncScroll.ts │ │ │ │ ├── useWindowResize.ts │ │ │ │ └── useDragAttributes.ts │ │ │ ├── store │ │ │ │ └── context.ts │ │ │ ├── positionManger │ │ │ │ ├── usePosition.ts │ │ │ │ └── context.ts │ │ │ ├── index.tsx │ │ │ └── components │ │ │ │ ├── hoc │ │ │ │ └── DateProvider.tsx │ │ │ │ └── events │ │ │ │ └── EmptyAgenda.tsx │ │ ├── ScrollToTop.tsx │ │ ├── PositionInput.tsx │ │ ├── NProgressIndicator.tsx │ │ ├── Progress.tsx │ │ ├── InfoBox.tsx │ │ ├── Hidden.tsx │ │ ├── Unauthorized.tsx │ │ ├── AgencyBadge.tsx │ │ ├── Error.tsx │ │ ├── Available.tsx │ │ └── SimpleBackdrop.tsx │ ├── services │ │ └── axiosInstance.ts │ ├── lang │ │ ├── booking-filter.ts │ │ ├── users.ts │ │ ├── bookings.ts │ │ ├── no-match.ts │ │ ├── unauthorized.ts │ │ ├── create-booking.ts │ │ ├── update-user.ts │ │ ├── create-user.ts │ │ ├── hidden.ts │ │ ├── agencies.ts │ │ ├── sold-out.ts │ │ ├── booking.ts │ │ ├── update-country.ts │ │ ├── update-location.ts │ │ ├── booking-property-list.ts │ │ ├── activate.ts │ │ ├── settings.ts │ │ ├── agency-list.ts │ │ ├── create-country.ts │ │ ├── rental-term.ts │ │ ├── available.ts │ │ ├── image-editor.ts │ │ ├── contact-form.ts │ │ ├── create-location.ts │ │ ├── sign-in.ts │ │ ├── sign-up.ts │ │ ├── countries.ts │ │ ├── user-list.ts │ │ ├── locations.ts │ │ ├── reset-password.ts │ │ └── create-agency.ts │ ├── pages │ │ ├── ToS.tsx │ │ ├── Notifications.tsx │ │ ├── Error.tsx │ │ ├── About.tsx │ │ ├── Contact.tsx │ │ └── NoMatch.tsx │ ├── utils │ │ ├── customHooks.ts │ │ └── langHelper.ts │ └── context │ │ └── RecaptchaContext.tsx ├── public │ ├── favicon.ico │ └── robots.txt ├── types │ └── eslint-plugin-react-compiler.d.ts ├── tsconfig.node.json ├── Dockerfile ├── index.html ├── .gitignore ├── nginx.conf ├── Dockerfile.dev └── .env.example ├── frontend ├── src │ ├── vite-env.d.ts │ ├── assets │ │ ├── img │ │ │ ├── paypal.png │ │ │ ├── stripe.png │ │ │ ├── apple-icon.png │ │ │ ├── google-icon.png │ │ │ ├── view-on-map.png │ │ │ └── facebook-icon.png │ │ └── css │ │ │ ├── no-match.css │ │ │ ├── badge.css │ │ │ ├── error.css │ │ │ ├── progress.css │ │ │ ├── agencies.css │ │ │ ├── locations.css │ │ │ ├── index.css │ │ │ ├── contact.css │ │ │ ├── booking-filter.css │ │ │ ├── map-dialog.css │ │ │ ├── newsletter-form.css │ │ │ ├── tos.css │ │ │ ├── privacy.css │ │ │ ├── property-list.css │ │ │ ├── cookie-policy.css │ │ │ ├── checkout-session.css │ │ │ ├── view-on-map-button.css │ │ │ ├── extras.css │ │ │ ├── map.css │ │ │ ├── property-filter.css │ │ │ ├── pager.css │ │ │ ├── contact-form.css │ │ │ ├── rental-term-filter.css │ │ │ ├── property-type-filter.css │ │ │ ├── social-login.css │ │ │ ├── about.css │ │ │ ├── toast.css │ │ │ ├── agency-badge.css │ │ │ ├── multiple-select.css │ │ │ ├── reset-password.css │ │ │ ├── forgot-password.css │ │ │ ├── status-list.css │ │ │ └── status-filter.css │ ├── config │ │ └── const.ts │ ├── services │ │ ├── axiosInstance.ts │ │ ├── IpInfoService.ts │ │ ├── CountryService.ts │ │ └── AgencyService.ts │ ├── lang │ │ ├── search.ts │ │ ├── booking.ts │ │ ├── booking-filter.ts │ │ ├── bookings.ts │ │ ├── no-match.ts │ │ ├── view-on-map-button.ts │ │ ├── map.ts │ │ ├── unauthorized.ts │ │ ├── sold-out.ts │ │ ├── booking-property-list.ts │ │ ├── sign-up.ts │ │ ├── activate.ts │ │ ├── location-carrousel.ts │ │ ├── settings.ts │ │ ├── newsletter-form.ts │ │ ├── rental-term.ts │ │ ├── contact-form.ts │ │ ├── sign-in.ts │ │ ├── reset-password.ts │ │ └── change-password.ts │ ├── components │ │ ├── ScrollToTop.tsx │ │ ├── NProgressIndicator.tsx │ │ ├── Badge.tsx │ │ ├── Progress.tsx │ │ ├── ViewOnMapButton.tsx │ │ ├── Error.tsx │ │ ├── Unauthorized.tsx │ │ ├── AgencyBadge.tsx │ │ ├── TabPanel.tsx │ │ ├── SimpleBackdrop.tsx │ │ └── Toast.tsx │ ├── utils │ │ ├── useAnalytics.ts │ │ ├── customHooks.ts │ │ ├── langHelper.ts │ │ └── ga4.ts │ ├── pages │ │ ├── Error.tsx │ │ ├── Agencies.tsx │ │ ├── ToS.tsx │ │ ├── Privacy.tsx │ │ ├── CookiePolicy.tsx │ │ ├── Notifications.tsx │ │ ├── Info.tsx │ │ ├── NoMatch.tsx │ │ ├── Contact.tsx │ │ └── About.tsx │ └── context │ │ ├── PayPalContext.tsx │ │ └── RecaptchaContext.tsx ├── .stylelintrc.json ├── public │ ├── cover.mp4 │ ├── cover.png │ ├── cover.webp │ ├── favicon.ico │ └── robots.txt ├── types │ └── eslint-plugin-react-compiler.d.ts ├── tsconfig.node.json ├── Dockerfile ├── .gitignore ├── index.html ├── nginx.conf └── Dockerfile.dev ├── __scripts ├── swap-usage.sh ├── utils.sh ├── mi-logs.sh ├── free-mem.sh ├── swap.sh ├── mi-deploy-backend.sh ├── mi-deploy.sh ├── mi-deploy-frontend.sh └── mi-deploy-admin.sh ├── .vscode ├── extensions.json └── settings.json ├── backend ├── __tests__ │ ├── img │ │ ├── avatar1.jpg │ │ ├── avatar2.png │ │ ├── main1.jpg │ │ ├── main2.jpg │ │ ├── location0.jpg │ │ ├── location1.jpg │ │ ├── location2.jpg │ │ ├── additional1-1.jpg │ │ ├── additional1-2.jpg │ │ ├── additional2-1.jpg │ │ └── additional2-2.jpg │ └── config.test.ts ├── src │ ├── config │ │ ├── ipinfoRoutes.config.ts │ │ ├── paypalRoutes.config.ts │ │ ├── stripeRoutes.config.ts │ │ ├── agencyRoutes.config.ts │ │ ├── notificationRoutes.config.ts │ │ ├── countryRoutes.config.ts │ │ ├── bookingRoutes.config.ts │ │ ├── propertyRoutes.config.ts │ │ └── locationRoutes.config.ts │ ├── payment │ │ └── stripe.ts │ ├── lang │ │ └── i18n.ts │ ├── routes │ │ ├── ipinfoRoutes.ts │ │ ├── paypalRoutes.ts │ │ ├── stripeRoutes.ts │ │ ├── agencyRoutes.ts │ │ └── notificationRoutes.ts │ ├── controllers │ │ └── ipinfoController.ts │ ├── utils │ │ └── databaseTTLHelper.ts │ ├── models │ │ ├── Country.ts │ │ ├── PushToken.ts │ │ ├── NotificationCounter.ts │ │ ├── Notification.ts │ │ ├── Token.ts │ │ └── Location.ts │ └── middlewares │ │ ├── allowedMethods.ts │ │ └── cors.ts ├── nodemon.json ├── Dockerfile ├── .gitignore ├── jest.config.json ├── babel.config.js └── Dockerfile.dev ├── .github ├── FUNDING.yml ├── latest-release.json └── releases.yml ├── codecov.yml ├── .gitignore ├── packages ├── currency-converter │ ├── check.ts │ └── package.json ├── .gitignore ├── movinin-types │ └── package.json ├── disable-react-devtools │ ├── package.json │ └── index.ts ├── reactjs-social-login │ ├── .gitignore │ ├── package.json │ ├── tsconfig.json │ └── src │ │ └── index.tsx └── movinin-helper │ └── package.json ├── .dockerignore └── __services └── movinin.service /mobile/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npm run pre-commit 4 | -------------------------------------------------------------------------------- /admin/.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { "extends": ["stylelint-config-standard"] } -------------------------------------------------------------------------------- /admin/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /frontend/.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { "extends": ["stylelint-config-standard"] } -------------------------------------------------------------------------------- /__scripts/swap-usage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | grep '^Swap' /proc/meminfo 4 | -------------------------------------------------------------------------------- /admin/src/assets/css/search.css: -------------------------------------------------------------------------------- 1 | .sc-search { 2 | width: 235px; 3 | } 4 | -------------------------------------------------------------------------------- /__scripts/utils.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | grep CRON-FREE-MEM /var/log/syslog 4 | -------------------------------------------------------------------------------- /__scripts/mi-logs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | tail -f /opt/movinin/backend/logs/all.log 4 | -------------------------------------------------------------------------------- /mobile/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/mobile/assets/icon.png -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/admin/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/cover.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/public/cover.mp4 -------------------------------------------------------------------------------- /frontend/public/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/public/cover.png -------------------------------------------------------------------------------- /mobile/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/mobile/assets/splash.png -------------------------------------------------------------------------------- /admin/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /admin/src/types/index.d.ts: -------------------------------------------------------------------------------- 1 | interface ImageItem { 2 | filename: string 3 | temp?: boolean 4 | } 5 | -------------------------------------------------------------------------------- /frontend/public/cover.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/public/cover.webp -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /admin/src/assets/img/property.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/admin/src/assets/img/property.png -------------------------------------------------------------------------------- /backend/__tests__/img/avatar1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/avatar1.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/avatar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/avatar2.png -------------------------------------------------------------------------------- /backend/__tests__/img/main1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/main1.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/main2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/main2.jpg -------------------------------------------------------------------------------- /mobile/assets/secure-payment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/mobile/assets/secure-payment.png -------------------------------------------------------------------------------- /mobile/assets/splash-tablet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/mobile/assets/splash-tablet.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: aelassas 2 | buy_me_a_coffee: aelassas 3 | custom: ["https://www.paypal.me/aelassaspp"] 4 | -------------------------------------------------------------------------------- /admin/src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | .app { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | } 6 | -------------------------------------------------------------------------------- /backend/__tests__/img/location0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/location0.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/location1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/location1.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/location2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/location2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/src/assets/img/paypal.png -------------------------------------------------------------------------------- /frontend/src/assets/img/stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/src/assets/img/stripe.png -------------------------------------------------------------------------------- /.github/latest-release.json: -------------------------------------------------------------------------------- 1 | {"latestApkUrl": "https://github.com/aelassas/movinin/releases/download/v6.5/movinin-6.5.apk"} 2 | -------------------------------------------------------------------------------- /frontend/src/assets/img/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/src/assets/img/apple-icon.png -------------------------------------------------------------------------------- /backend/__tests__/img/additional1-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/additional1-1.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/additional1-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/additional1-2.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/additional2-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/additional2-1.jpg -------------------------------------------------------------------------------- /backend/__tests__/img/additional2-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/backend/__tests__/img/additional2-2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/css/no-match.css: -------------------------------------------------------------------------------- 1 | .no-match { 2 | margin: 15px; 3 | } 4 | 5 | .no-match h2 { 6 | color: #232323; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/assets/img/google-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/src/assets/img/google-icon.png -------------------------------------------------------------------------------- /frontend/src/assets/img/view-on-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/src/assets/img/view-on-map.png -------------------------------------------------------------------------------- /frontend/src/assets/img/facebook-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aelassas/movinin/HEAD/frontend/src/assets/img/facebook-icon.png -------------------------------------------------------------------------------- /backend/src/config/ipinfoRoutes.config.ts: -------------------------------------------------------------------------------- 1 | const routes = { 2 | getCountryCode: '/api/country-code', 3 | } 4 | 5 | export default routes 6 | -------------------------------------------------------------------------------- /frontend/src/assets/css/badge.css: -------------------------------------------------------------------------------- 1 | div.badge { 2 | font-size: 11px; 3 | border-radius: 10px; 4 | width: fit-content; 5 | padding: 3px 12px; 6 | } 7 | -------------------------------------------------------------------------------- /__scripts/free-mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | free -h 4 | sudo sysctl -w vm.drop_caches=3 5 | sudo sync 6 | echo 3 | sudo tee /proc/sys/vm/drop_caches 7 | free -h 8 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: off # disables overall project coverage check 4 | patch: off # disables patch coverage check 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /**/*.key 2 | /**/*.crt 3 | /**/*.pem 4 | /**/*.pem-chain 5 | /**/*.ca.pem 6 | /**/.DS_Store 7 | /**/dist 8 | /node_modules 9 | .eslintcache 10 | -------------------------------------------------------------------------------- /admin/src/assets/css/error.css: -------------------------------------------------------------------------------- 1 | /* Error */ 2 | 3 | .error { 4 | color: #ec5555; 5 | text-align: center; 6 | } 7 | 8 | .message { 9 | padding: 5px; 10 | } 11 | -------------------------------------------------------------------------------- /admin/src/assets/css/progress.css: -------------------------------------------------------------------------------- 1 | div.progress { 2 | width: 100%; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | padding: 10px 0; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/assets/css/error.css: -------------------------------------------------------------------------------- 1 | /* Error */ 2 | 3 | .error { 4 | color: #ec5555; 5 | text-align: center; 6 | } 7 | 8 | .message { 9 | padding: 5px; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/assets/css/progress.css: -------------------------------------------------------------------------------- 1 | div.progress { 2 | width: 100%; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | padding: 10px 0; 7 | } 8 | -------------------------------------------------------------------------------- /admin/src/config/const.ts: -------------------------------------------------------------------------------- 1 | const Const = { 2 | PAGINATION_MODE: { 3 | CLASSIC: 'CLASSIC', 4 | INFINITE_SCROLL: 'INFINITE_SCROLL', 5 | }, 6 | } 7 | 8 | export default Const 9 | -------------------------------------------------------------------------------- /frontend/src/config/const.ts: -------------------------------------------------------------------------------- 1 | const Const = { 2 | PAGINATION_MODE: { 3 | CLASSIC: 'CLASSIC', 4 | INFINITE_SCROLL: 'INFINITE_SCROLL', 5 | }, 6 | } 7 | 8 | export default Const 9 | -------------------------------------------------------------------------------- /backend/src/payment/stripe.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe' 2 | import * as env from '../config/env.config' 3 | 4 | const stripeAPI = new Stripe(env.STRIPE_SECRET_KEY) 5 | 6 | export default stripeAPI 7 | -------------------------------------------------------------------------------- /admin/src/components/scheduler/helpers/constants.ts: -------------------------------------------------------------------------------- 1 | export const BORDER_HEIGHT = 1 2 | export const MULTI_DAY_EVENT_HEIGHT = 28 3 | export const MONTH_NUMBER_HEIGHT = 27 4 | export const MONTH_BAR_HEIGHT = 23 5 | -------------------------------------------------------------------------------- /admin/types/eslint-plugin-react-compiler.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'eslint-plugin-react-compiler' { 2 | import type { ESLint } from 'eslint' 3 | 4 | let plugin: ESLint.Plugin 5 | export default plugin 6 | } 7 | -------------------------------------------------------------------------------- /admin/src/services/axiosInstance.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import env from '@/config/env.config' 3 | 4 | const axiosInstance = axios.create({ baseURL: env.API_HOST }) 5 | 6 | export default axiosInstance 7 | -------------------------------------------------------------------------------- /frontend/types/eslint-plugin-react-compiler.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'eslint-plugin-react-compiler' { 2 | import type { ESLint } from 'eslint' 3 | 4 | let plugin: ESLint.Plugin 5 | export default plugin 6 | } 7 | -------------------------------------------------------------------------------- /mobile/lang/i18n.ts: -------------------------------------------------------------------------------- 1 | import { I18n } from 'i18n-js' 2 | import { en } from './en' 3 | import { fr } from './fr' 4 | 5 | const i18n = new I18n({ en, fr }) 6 | i18n.enableFallback = true 7 | 8 | export default i18n 9 | -------------------------------------------------------------------------------- /backend/src/config/paypalRoutes.config.ts: -------------------------------------------------------------------------------- 1 | const routes = { 2 | createPayPalOrder: '/api/create-paypal-order', 3 | checkPayPalOrder: '/api/check-paypal-order/:bookingId/:orderId', 4 | } 5 | 6 | export default routes 7 | -------------------------------------------------------------------------------- /backend/src/lang/i18n.ts: -------------------------------------------------------------------------------- 1 | import { I18n } from 'i18n-js' 2 | import { en } from './en' 3 | import { fr } from './fr' 4 | 5 | const i18n = new I18n({ en, fr }) 6 | i18n.enableFallback = true 7 | 8 | export default i18n 9 | -------------------------------------------------------------------------------- /frontend/src/services/axiosInstance.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import env from '@/config/env.config' 3 | 4 | const axiosInstance = axios.create({ baseURL: env.API_HOST }) 5 | 6 | export default axiosInstance 7 | -------------------------------------------------------------------------------- /frontend/src/assets/css/agencies.css: -------------------------------------------------------------------------------- 1 | div.agencies { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | min-height: 100vh; 8 | } 9 | -------------------------------------------------------------------------------- /admin/src/components/scheduler/hooks/useStore.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import { StoreContext } from '../store/context' 3 | 4 | const useStore = () => useContext(StoreContext) 5 | 6 | export default useStore 7 | -------------------------------------------------------------------------------- /admin/src/components/scheduler/store/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react' 2 | import { initialStore } from './default' 3 | import { Store } from './types' 4 | 5 | export const StoreContext = createContext(initialStore) 6 | -------------------------------------------------------------------------------- /backend/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": [], 5 | "exec": "tsx --experimental-specifier-resolution=node --import ./src/monitoring/instrument.ts ./src", 6 | "legacyWatch": true 7 | } 8 | -------------------------------------------------------------------------------- /admin/src/components/scheduler/positionManger/usePosition.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import { PositionContext } from './context' 3 | 4 | const usePosition = () => useContext(PositionContext) 5 | 6 | export default usePosition 7 | -------------------------------------------------------------------------------- /admin/src/assets/css/contact.css: -------------------------------------------------------------------------------- 1 | div.contact { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | } 8 | 9 | div.contact .form { 10 | margin: 100px 0; 11 | } -------------------------------------------------------------------------------- /backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM node:lts-alpine 4 | WORKDIR /movinin/backend 5 | COPY ./backend ./ 6 | COPY ./packages /movinin/packages 7 | RUN npm install 8 | 9 | CMD [ "npm", "run", "start:setup"] 10 | EXPOSE 4004 11 | -------------------------------------------------------------------------------- /frontend/src/assets/css/locations.css: -------------------------------------------------------------------------------- 1 | div.locations { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | } 8 | 9 | div.locations .map { 10 | height: 800px; 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/config/stripeRoutes.config.ts: -------------------------------------------------------------------------------- 1 | const routes = { 2 | createCheckoutSession: '/api/create-checkout-session', 3 | checkCheckoutSession: '/api/check-checkout-session/:sessionId', 4 | createPaymentIntent: '/api/create-payment-intent', 5 | } 6 | 7 | export default routes 8 | -------------------------------------------------------------------------------- /frontend/src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | .app { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | } 6 | 7 | /* .grecaptcha-badge { 8 | visibility: hidden !important; 9 | } */ 10 | 11 | .github-fork-ribbon::before { 12 | background-color: #272727; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/assets/css/contact.css: -------------------------------------------------------------------------------- 1 | div.contact { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | min-height: 100vh; 8 | } 9 | 10 | div.contact .form { 11 | margin: 100px 0; 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/lang/search.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | }, 7 | en: { 8 | }, 9 | }) 10 | 11 | langHelper.setLanguage(strings) 12 | export { strings } 13 | -------------------------------------------------------------------------------- /packages/currency-converter/check.ts: -------------------------------------------------------------------------------- 1 | import CurrencyConverter from './index.js' 2 | 3 | const amount = 100 4 | const currencyConverter = new CurrencyConverter({ from: 'USD', to: 'EUR', amount }) 5 | 6 | const res = await currencyConverter.convert() 7 | 8 | console.log(`${amount} USD = ${res} EUR`) 9 | -------------------------------------------------------------------------------- /admin/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true 9 | }, 10 | "include": ["vite.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true 9 | }, 10 | "include": ["vite.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /mobile/services/axiosInstance.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import * as axiosHelper from '@/utils/axiosHelper' 3 | import * as env from '@/config/env.config' 4 | 5 | const axiosInstance = axios.create({ baseURL: env.API_HOST }) 6 | 7 | axiosHelper.init(axiosInstance) 8 | 9 | export default axiosInstance 10 | -------------------------------------------------------------------------------- /admin/src/assets/css/booking-filter.css: -------------------------------------------------------------------------------- 1 | div.booking-filter { 2 | background: #fafafa; 3 | margin: 10px 10px 0 0; 4 | border: 1px solid #dadada; 5 | font-size: 13px; 6 | } 7 | 8 | div.booking-filter .bf-search { 9 | margin-top: 7px; 10 | } 11 | 12 | div.booking-filter .btn-search { 13 | margin: 20px 0; 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/assets/css/booking-filter.css: -------------------------------------------------------------------------------- 1 | div.booking-filter { 2 | background: #fff; 3 | margin: 10px 10px 0 0; 4 | border: 1px solid #dadada; 5 | font-size: 13px; 6 | } 7 | 8 | div.booking-filter .bf-search { 9 | margin-top: 7px; 10 | } 11 | 12 | div.booking-filter .btn-search { 13 | margin: 20px 0; 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/assets/css/map-dialog.css: -------------------------------------------------------------------------------- 1 | .map-dialog-content { 2 | margin: 0; 3 | width: 100%; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | } 8 | 9 | .close-icon { 10 | color: #fff; 11 | font-size: 20px !important; 12 | } 13 | 14 | .close-btn:hover > * { 15 | color: #d1d1d1; 16 | } 17 | -------------------------------------------------------------------------------- /mobile/components/AutocompleteDropdown-v4.3.1/types/global.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace setInterval { 3 | function setInterval(callback: () => void, ms?: number | undefined): NodeJS.Timeout 4 | } 5 | namespace setTimeout { 6 | function setTimeout(callback: () => void, ms?: number | undefined): NodeJS.Timeout 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /mobile/components/AutocompleteDropdown-v4/types/global.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace setInterval { 3 | function setInterval(callback: () => void, ms?: number | undefined): NodeJS.Timeout 4 | } 5 | namespace setTimeout { 6 | function setTimeout(callback: () => void, ms?: number | undefined): NodeJS.Timeout 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/config/agencyRoutes.config.ts: -------------------------------------------------------------------------------- 1 | const routes = { 2 | validate: '/api/validate-agency', 3 | update: '/api/update-agency', 4 | delete: '/api/delete-agency/:id', 5 | getAgency: '/api/agency/:id', 6 | getAgencies: '/api/agencies/:page/:size', 7 | getAllAgencies: '/api/all-agencies', 8 | } 9 | 10 | export default routes 11 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /**/.git 2 | /**/node_modules 3 | /**/dist 4 | /**/logs 5 | /**/tsconfig.tsbuildinfo 6 | /**/vite.config.d.ts 7 | /**/vite.config.js 8 | /**/.env 9 | /**/.env.example 10 | /**/.env.development 11 | /**/.env.production 12 | /**/.dockerignore 13 | /**/Dockerfile 14 | mobile/ 15 | .github/ 16 | .vscode/ 17 | __scripts/ 18 | __services/ 19 | -------------------------------------------------------------------------------- /admin/src/components/ScrollToTop.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { useLocation } from 'react-router-dom' 3 | 4 | const ScrollToTop = () => { 5 | const { pathname } = useLocation() 6 | 7 | useEffect(() => { 8 | window.scrollTo(0, 0) 9 | }, [pathname]) 10 | 11 | return null 12 | } 13 | 14 | export default ScrollToTop 15 | -------------------------------------------------------------------------------- /frontend/src/lang/booking.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | TOTAL: 'Total :', 7 | }, 8 | en: { 9 | TOTAL: 'Total:', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /mobile/components/Indicator.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { ActivityIndicator } from 'react-native' 3 | 4 | interface IndicatorProps { 5 | style?: object 6 | } 7 | 8 | const Indicator = ({ style }: IndicatorProps) => ( 9 | 10 | ) 11 | 12 | export default Indicator 13 | -------------------------------------------------------------------------------- /backend/src/routes/ipinfoRoutes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import routeNames from '../config/ipinfoRoutes.config' 3 | import * as ipinfoController from '../controllers/ipinfoController' 4 | 5 | const routes = express.Router() 6 | 7 | routes.route(routeNames.getCountryCode).get(ipinfoController.getCountryCode) 8 | 9 | export default routes 10 | -------------------------------------------------------------------------------- /frontend/src/components/ScrollToTop.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { useLocation } from 'react-router-dom' 3 | 4 | const ScrollToTop = () => { 5 | const { pathname } = useLocation() 6 | 7 | useEffect(() => { 8 | window.scrollTo(0, 0) 9 | }, [pathname]) 10 | 11 | return null 12 | } 13 | 14 | export default ScrollToTop 15 | -------------------------------------------------------------------------------- /admin/src/lang/booking-filter.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | LOCATION: 'Lieu', 7 | }, 8 | en: { 9 | LOCATION: 'location', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /frontend/src/lang/booking-filter.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | LOCATION: 'Lieu', 7 | }, 8 | en: { 9 | LOCATION: 'location', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /admin/src/lang/users.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NEW_USER: 'Nouvel utilisateur', 7 | }, 8 | en: { 9 | NEW_USER: 'New user', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /admin/src/assets/css/property-scheduler-filter.css: -------------------------------------------------------------------------------- 1 | div.property-scheduler-filter { 2 | background: #fafafa; 3 | margin: 10px 10px 0 0; 4 | border: 1px solid #dadada; 5 | font-size: 13px; 6 | } 7 | 8 | div.property-scheduler-filter .bf-search { 9 | margin-top: 7px; 10 | } 11 | 12 | div.property-scheduler-filter .btn-search { 13 | margin: 20px 0; 14 | } 15 | -------------------------------------------------------------------------------- /packages/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /**/node_modules/ 5 | npm-debug.log* 6 | 7 | # TypeScript 8 | /**/*.tsbuildinfo 9 | /**/*.d.ts 10 | 11 | # JavaScript 12 | /**/*.js 13 | 14 | # misc 15 | /**/.DS_Store 16 | /**/.DS_Store? 17 | 18 | # eslint 19 | /**/.eslintcache 20 | -------------------------------------------------------------------------------- /admin/src/lang/bookings.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NEW_BOOKING: 'Nouvelle réservation', 7 | }, 8 | en: { 9 | NEW_BOOKING: 'New Booking', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /admin/src/lang/no-match.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NO_MATCH: 'Rien à voir ici !', 7 | }, 8 | en: { 9 | NO_MATCH: 'Nothing to see here!', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /frontend/src/lang/bookings.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NEW_BOOKING: 'Nouvelle réservation', 7 | }, 8 | en: { 9 | NEW_BOOKING: 'New Booking', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /frontend/src/lang/no-match.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NO_MATCH: 'Rien à voir ici !', 7 | }, 8 | en: { 9 | NO_MATCH: 'Nothing to see here!', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /admin/src/components/PositionInput.tsx: -------------------------------------------------------------------------------- 1 | import React, { ComponentPropsWithoutRef } from 'react' 2 | import { Input } from '@mui/material' 3 | 4 | const PositionInput = (props: ComponentPropsWithoutRef) => ( 5 | 10 | ) 11 | 12 | export default PositionInput 13 | -------------------------------------------------------------------------------- /admin/src/lang/unauthorized.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | UNAUTHORIZED: 'Accès non autorisé', 7 | }, 8 | en: { 9 | UNAUTHORIZED: 'Unauthorized access', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /frontend/src/assets/css/newsletter-form.css: -------------------------------------------------------------------------------- 1 | form.newsletter-form div.form { 2 | display: flex; 3 | flex-direction: row; 4 | align-items: center; 5 | } 6 | 7 | form.newsletter-form div.form .input { 8 | margin-right: 15px; 9 | max-width: 240px; 10 | } 11 | 12 | form.newsletter-form div.form .btn { 13 | height: 40px; 14 | padding: 0 30px; 15 | min-width: 120px; 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/lang/view-on-map-button.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | VIEW_ON_MAP: 'Voir sur la carte', 7 | }, 8 | en: { 9 | VIEW_ON_MAP: 'View on map', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /__scripts/swap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SWAP_SIZE="1G" # Swap size of 1GB 4 | 5 | # Add Swap Space 6 | echo "Adding swap space..." 7 | sudo fallocate -l $SWAP_SIZE /swapfile 8 | sudo chmod 600 /swapfile 9 | sudo mkswap /swapfile 10 | sudo swapon /swapfile 11 | 12 | # Make swap permanent 13 | echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab 14 | 15 | grep '^Swap' /proc/meminfo 16 | -------------------------------------------------------------------------------- /frontend/src/lang/map.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | SELECT_LOCATION: 'Choisir cette destination', 7 | }, 8 | en: { 9 | SELECT_LOCATION: 'Select Destination', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /admin/src/lang/create-booking.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NEW_BOOKING_HEADING: 'Nouvelle réservation', 7 | }, 8 | en: { 9 | NEW_BOOKING_HEADING: 'New booking', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /frontend/src/services/IpInfoService.ts: -------------------------------------------------------------------------------- 1 | import axiosInstance from './axiosInstance' 2 | 3 | /** 4 | * Returns Country ISO 2 code from client IP. 5 | * 6 | * @param {string} sessionId 7 | * @returns {Promise} 8 | */ 9 | export const getCountryCode = (): Promise => 10 | axiosInstance 11 | .get( 12 | '/api/country-code', 13 | ) 14 | .then((res) => res.data) 15 | -------------------------------------------------------------------------------- /frontend/src/utils/useAnalytics.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { useLocation } from 'react-router-dom' 3 | 4 | import * as analytics from './ga4' 5 | 6 | export const useAnalytics = () => { 7 | const location = useLocation() 8 | 9 | useEffect(() => { 10 | const path = location.pathname + location.search 11 | analytics.sendPageview(path) 12 | }, [location]) 13 | } 14 | -------------------------------------------------------------------------------- /__services/movinin.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Movin' In backend server 3 | Wants=mongod.service 4 | After=mongod.service 5 | 6 | [Service] 7 | ExecStart=/usr/bin/npm start 8 | WorkingDirectory=/opt/movinin/backend 9 | Type=simple 10 | Restart=always 11 | StandardOutput=append:/var/log/movinin.log 12 | StandardError=append:/var/log/movinin.log 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /admin/src/lang/update-user.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | UPDATE_USER_HEADING: "Modification de l'utilisateur", 7 | }, 8 | en: { 9 | UPDATE_USER_HEADING: 'User update', 10 | }, 11 | }) 12 | 13 | langHelper.setLanguage(strings) 14 | export { strings } 15 | -------------------------------------------------------------------------------- /backend/src/config/notificationRoutes.config.ts: -------------------------------------------------------------------------------- 1 | const routes = { 2 | notificationCounter: '/api/notification-counter/:userId', 3 | markAsRead: '/api/mark-notifications-as-read/:userId', 4 | markAsUnRead: '/api/mark-notifications-as-unread/:userId', 5 | delete: '/api/delete-notifications/:userId', 6 | getNotifications: '/api/notifications/:userId/:page/:size', 7 | } 8 | 9 | export default routes 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "javascriptreact", 5 | "typescript", 6 | "typescriptreact" 7 | ], 8 | "eslint.run": "onType", 9 | "eslint.workingDirectories": [ 10 | { "directory": "backend" }, 11 | { "directory": "admin" }, 12 | { "directory": "frontend" }, 13 | { "directory": "mobile" } 14 | ], 15 | "files.insertFinalNewline": true 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/assets/css/tos.css: -------------------------------------------------------------------------------- 1 | div.tos { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | white-space: pre-wrap; 8 | padding: 50px 20%; 9 | font-size: 15px; 10 | color: #121212; 11 | min-height: 100vh; 12 | } 13 | 14 | @media only screen and (width <=960px) { 15 | div.tos { 16 | padding: 30px 20px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/movinin-types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "movinin-types", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "build": "rimraf ./index.js ./index.d.ts && tsc" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "rimraf": "^5.0.1", 15 | "typescript": "^5.2.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frontend/src/assets/css/privacy.css: -------------------------------------------------------------------------------- 1 | div.privacy { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | white-space: pre-wrap; 8 | padding: 50px 20%; 9 | font-size: 15px; 10 | color: #121212; 11 | min-height: 100vh; 12 | } 13 | 14 | @media only screen and (width <=960px) { 15 | div.privacy { 16 | padding: 30px 20px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/pages/Error.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from '@mui/material' 3 | import { strings as commonStrings } from '@/lang/common' 4 | 5 | const Error = ({ style }: { style?: React.CSSProperties }) => ( 6 |
7 |

{commonStrings.GENERIC_ERROR}

8 | {commonStrings.GO_TO_HOME} 9 |
10 | ) 11 | 12 | export default Error 13 | -------------------------------------------------------------------------------- /frontend/src/assets/css/property-list.css: -------------------------------------------------------------------------------- 1 | section.property-list .empty-list { 2 | margin-top: 15px; 3 | text-align: center; 4 | width: 250px; 5 | } 6 | 7 | section.property-list { 8 | padding-top: 10px; 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | } 13 | 14 | @media only screen and (width >=500px) and (width <=960px) { 15 | section.property-list { 16 | max-width: 480px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/disable-react-devtools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "disable-react-devtools", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "build": "rimraf ./index.js ./index.d.ts && tsc" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "rimraf": "^5.0.1", 15 | "typescript": "^5.2.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/routes/paypalRoutes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import routeNames from '../config/paypalRoutes.config' 3 | import * as paypalController from '../controllers/paypalController' 4 | 5 | const routes = express.Router() 6 | 7 | routes.route(routeNames.createPayPalOrder).post(paypalController.createPayPalOrder) 8 | routes.route(routeNames.checkPayPalOrder).post(paypalController.checkPayPalOrder) 9 | 10 | export default routes 11 | -------------------------------------------------------------------------------- /frontend/src/assets/css/cookie-policy.css: -------------------------------------------------------------------------------- 1 | div.cookie-policy { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | white-space: pre-wrap; 8 | padding: 50px 20%; 9 | font-size: 15px; 10 | color: #121212; 11 | min-height: 100vh; 12 | } 13 | 14 | @media only screen and (width <=960px) { 15 | div.cookie-policy { 16 | padding: 30px 20px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /admin/src/assets/css/tos.css: -------------------------------------------------------------------------------- 1 | div.tos { 2 | display: flex; 3 | flex-direction: column; 4 | flex: 1 0 auto; 5 | align-items: center; 6 | transform: translate3d(0, 0, 0); 7 | white-space: pre-wrap; 8 | padding: 50px 20%; 9 | font-size: 15px; 10 | color: #121212; 11 | min-height: 100vh; 12 | } 13 | 14 | @media only screen and (width <=960px) { 15 | div.tos { 16 | padding: 30px 20px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /admin/src/components/NProgressIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import NProgress from 'nprogress' 3 | 4 | import 'nprogress/nprogress.css' 5 | 6 | const NProgressIndicator = () => { 7 | useEffect(() => { 8 | NProgress.configure({ showSpinner: false }) 9 | NProgress.start() 10 | 11 | return () => { 12 | NProgress.done() 13 | } 14 | }, []) 15 | 16 | return null 17 | } 18 | 19 | export default NProgressIndicator 20 | -------------------------------------------------------------------------------- /frontend/src/lang/unauthorized.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | UNAUTHORIZED: 'Accès non autorisé', 7 | }, 8 | en: { 9 | UNAUTHORIZED: 'Unauthorized access', 10 | }, 11 | es: { 12 | UNAUTHORIZED: 'Acceso no autorizado', 13 | }, 14 | }) 15 | 16 | langHelper.setLanguage(strings) 17 | export { strings } 18 | -------------------------------------------------------------------------------- /admin/src/lang/create-user.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | CREATE_USER_HEADING: 'Nouvelle utilisateur', 7 | BIRTH_DATE: 'Date de naissance', 8 | }, 9 | en: { 10 | CREATE_USER_HEADING: 'New user', 11 | BIRTH_DATE: 'Birth date', 12 | }, 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /frontend/src/components/NProgressIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import NProgress from 'nprogress' 3 | 4 | import 'nprogress/nprogress.css' 5 | 6 | const NProgressIndicator = () => { 7 | useEffect(() => { 8 | NProgress.configure({ showSpinner: false }) 9 | NProgress.start() 10 | 11 | return () => { 12 | NProgress.done() 13 | } 14 | }, []) 15 | 16 | return null 17 | } 18 | 19 | export default NProgressIndicator 20 | -------------------------------------------------------------------------------- /admin/src/lang/hidden.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | HIDDEN: 'Cachée', 7 | HIDDEN_INFO: 'Cette propriété est cachée.', 8 | }, 9 | en: { 10 | HIDDEN: 'Hidden', 11 | HIDDEN_INFO: 'This property is hidden.', 12 | } 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | npm-debug.log* 6 | 7 | # TypeScript 8 | /dist 9 | *.tsbuildinfo 10 | 11 | # misc 12 | .DS_Store 13 | .DS_Store? 14 | .env 15 | .env.docker 16 | .env.dev 17 | .env.development 18 | .env.production 19 | 20 | # eslint 21 | .eslintcache 22 | 23 | # jest 24 | /coverage 25 | 26 | # logs 27 | /logs 28 | 29 | .eslintcache 30 | -------------------------------------------------------------------------------- /mobile/components/AutocompleteDropdown-v4/helpers.ts: -------------------------------------------------------------------------------- 1 | export const fadeInDownShort = { 2 | 0: { 3 | opacity: 0, 4 | transform: [{ translateY: -20 }], 5 | }, 6 | 1: { 7 | opacity: 1, 8 | transform: [{ translateY: 0 }], 9 | }, 10 | } 11 | 12 | export const fadeInUpShort = { 13 | 0: { 14 | opacity: 0, 15 | transform: [{ translateY: 20 }], 16 | }, 17 | 1: { 18 | opacity: 1, 19 | transform: [{ translateY: 0 }], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /mobile/components/AutocompleteDropdown-v4.3.1/helpers.ts: -------------------------------------------------------------------------------- 1 | export const fadeInDownShort = { 2 | 0: { 3 | opacity: 0, 4 | transform: [{ translateY: -20 }], 5 | }, 6 | 1: { 7 | opacity: 1, 8 | transform: [{ translateY: 0 }], 9 | }, 10 | } 11 | 12 | export const fadeInUpShort = { 13 | 0: { 14 | opacity: 0, 15 | transform: [{ translateY: 20 }], 16 | }, 17 | 1: { 18 | opacity: 1, 19 | transform: [{ translateY: 0 }], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /admin/src/lang/agencies.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | NEW_AGENCY: 'Nouvelle agence', 7 | AGENCY: 'agence', 8 | AGENCIES: 'agences', 9 | }, 10 | en: { 11 | NEW_AGENCY: 'New agency', 12 | AGENCY: 'agency', 13 | AGENCIES: 'agencies', 14 | }, 15 | }) 16 | 17 | langHelper.setLanguage(strings) 18 | export { strings } 19 | -------------------------------------------------------------------------------- /admin/src/pages/ToS.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { strings } from '@/lang/tos' 3 | import Layout from '@/components/Layout' 4 | 5 | import '@/assets/css/tos.css' 6 | 7 | const ToS = () => { 8 | const onLoad = () => { } 9 | 10 | return ( 11 | 12 |
13 |

{strings.TITLE}

14 |

{strings.TOS}

15 |
16 |
17 | ) 18 | } 19 | 20 | export default ToS 21 | -------------------------------------------------------------------------------- /admin/src/lang/sold-out.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | SOLD_OUT: 'Rupture', 7 | SOLD_OUT_INFO: 'Cette propriété est en rupture.', 8 | }, 9 | en: { 10 | SOLD_OUT: 'Sold out', 11 | SOLD_OUT_INFO: 'This property is sold out.', 12 | } 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /frontend/src/components/Badge.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import '@/assets/css/badge.css' 4 | 5 | interface BadgeProps { 6 | backgroundColor: string 7 | color: string 8 | text: string 9 | className?: string 10 | } 11 | 12 | const Badge = ({ 13 | backgroundColor, 14 | color, 15 | text, 16 | className, 17 | }: BadgeProps) => ( 18 |
{text}
19 | ) 20 | 21 | export default Badge 22 | -------------------------------------------------------------------------------- /admin/src/components/scheduler/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react' 2 | import SchedulerComponent from './SchedulerComponent' 3 | import { SchedulerProps, SchedulerRef } from './types' 4 | import { StoreProvider } from './store/provider' 5 | 6 | const Scheduler = forwardRef>((props, ref) => ( 7 | 8 | 9 | 10 | )) 11 | 12 | export { Scheduler } 13 | -------------------------------------------------------------------------------- /frontend/src/lang/sold-out.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | SOLD_OUT: 'Rupture', 7 | SOLD_OUT_INFO: 'Cette propriété est en rupture.', 8 | }, 9 | en: { 10 | SOLD_OUT: 'Sold out', 11 | SOLD_OUT_INFO: 'This property is sold out.', 12 | } 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /packages/reactjs-social-login/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # See https://help.github.com/ignore-files/ for more about ignoring files. 3 | 4 | # dependencies 5 | node_modules 6 | 7 | # builds 8 | build 9 | dist 10 | .rpt2_cache 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | .env.local 16 | .env.production 17 | .env.development 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | /src/helper/constants.ts 26 | -------------------------------------------------------------------------------- /admin/src/assets/css/hidden.css: -------------------------------------------------------------------------------- 1 | div.label { 2 | color: #fff; 3 | display: flex; 4 | flex-direction: row; 5 | align-items: center; 6 | justify-content: center; 7 | border-radius: 4px; 8 | font-size: 12px; 9 | padding: 2px 10px; 10 | margin: 2px 0; 11 | width: fit-content; 12 | height: 22px; 13 | } 14 | 15 | div.label .label-icon { 16 | font-size: 15px; 17 | margin-right: 5px; 18 | } 19 | 20 | div.hidden { 21 | background-color: #cfcfc4; 22 | } 23 | -------------------------------------------------------------------------------- /admin/src/lang/booking.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | TOTAL: 'Total :', 7 | DELETE_BOOKING: 'Êtes-vous sûr de vouloir supprimer cette réservation ?', 8 | }, 9 | en: { 10 | TOTAL: 'Total:', 11 | DELETE_BOOKING: 'Are you sure you want to delete this booking?', 12 | }, 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /admin/src/lang/update-country.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | UPDATE_COUNTRY: 'Modification du pays', 7 | COUNTRY_UPDATED: 'Pays modifié avec succès.', 8 | }, 9 | en: { 10 | UPDATE_COUNTRY: 'Country update', 11 | COUNTRY_UPDATED: 'Country updated successfully.', 12 | }, 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /admin/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM node:lts-alpine AS build 4 | WORKDIR /movinin/admin 5 | COPY ./admin ./ 6 | COPY ./admin/.env.docker .env 7 | COPY ./packages /movinin/packages 8 | RUN npm install --force 9 | RUN npm run build 10 | 11 | FROM nginx:stable-alpine 12 | WORKDIR /usr/share/nginx/html 13 | RUN rm -rf -- * 14 | COPY --from=build /movinin/admin/build . 15 | COPY ./admin/nginx.conf /etc/nginx/conf.d/default.conf 16 | CMD ["nginx", "-g", "daemon off;"] 17 | EXPOSE 3003 18 | -------------------------------------------------------------------------------- /admin/src/components/Progress.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { CircularProgress } from '@mui/material' 3 | 4 | import '@/assets/css/progress.css' 5 | 6 | interface ProgressProps { 7 | color?: 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning' | 'inherit' 8 | } 9 | 10 | const Progress = ({ color }: ProgressProps) => ( 11 |
12 | 13 |
14 | ) 15 | 16 | export default Progress 17 | -------------------------------------------------------------------------------- /frontend/src/components/Progress.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { CircularProgress } from '@mui/material' 3 | 4 | import '@/assets/css/progress.css' 5 | 6 | interface ProgressProps { 7 | color?: 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning' | 'inherit' 8 | } 9 | 10 | const Progress = ({ color }: ProgressProps) => ( 11 |
12 | 13 |
14 | ) 15 | 16 | export default Progress 17 | -------------------------------------------------------------------------------- /mobile/services/AgencyService.ts: -------------------------------------------------------------------------------- 1 | import axiosInstance from './axiosInstance' 2 | import * as axiosHelper from '@/utils/axiosHelper' 3 | import * as movininTypes from ':movinin-types' 4 | 5 | axiosHelper.init(axiosInstance) 6 | 7 | /** 8 | * Get all agencies. 9 | * 10 | * @returns {Promise} 11 | */ 12 | export const getAllAgencies = (): Promise => 13 | axiosInstance 14 | .get( 15 | '/api/all-agencies' 16 | ) 17 | .then((res) => res.data) 18 | -------------------------------------------------------------------------------- /admin/src/lang/update-location.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | UPDATE_LOCATION: 'Modification du lieu', 7 | LOCATION_UPDATED: 'Lieu modifié avec succès.', 8 | }, 9 | en: { 10 | UPDATE_LOCATION: 'Location update', 11 | LOCATION_UPDATED: 'Location updated successfully.', 12 | }, 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /mobile/components/Error.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { StyleSheet, View, Text } from 'react-native' 3 | 4 | interface ErrorProps { 5 | style?: object 6 | message: string 7 | } 8 | 9 | const Error = ({ 10 | style, 11 | message 12 | }: ErrorProps) => ( 13 | 14 | {message} 15 | 16 | ) 17 | 18 | const styles = StyleSheet.create({ 19 | text: { 20 | color: '#d32f2f', 21 | }, 22 | }) 23 | 24 | export default Error 25 | -------------------------------------------------------------------------------- /frontend/src/assets/css/checkout-session.css: -------------------------------------------------------------------------------- 1 | div.checkout-session { 2 | background-color: #F5F5F5; 3 | display: flex; 4 | flex: 1 0 auto; 5 | flex-direction: column; 6 | justify-content: flex-start; 7 | width: 100%; 8 | min-height: calc(100vh - 65px); 9 | transform: translate3d(0, 0, 0); 10 | } 11 | 12 | div.checkout-session .status { 13 | margin: 40px 0 0 30px; 14 | } 15 | 16 | @media only screen and (width <=960px) { 17 | div.checkout-session .status { 18 | margin: 40px 10px 0 10px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/movinin-helper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "movinin-helper", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "build": "rimraf ./tsconfig.tsbuildinfo ./index.js ./index.d.ts && tsc --build --verbose" 9 | }, 10 | "author": "Akram El Assas", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "rimraf": "^5.0.1", 14 | "typescript": "^5.2.2" 15 | }, 16 | "dependencies": { 17 | "@babel/runtime": "^7.26.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /admin/src/lang/booking-property-list.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | REQUIRED_FIELD: 'Veuillez renseigner le champ : ', 7 | REQUIRED_FIELDS: 'Veuillez renseigner les champs : ', 8 | }, 9 | en: { 10 | REQUIRED_FIELD: 'Please fill in the field: ', 11 | REQUIRED_FIELDS: 'Please fill in the fields: ', 12 | }, 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM node:lts-alpine AS build 4 | WORKDIR /movinin/frontend 5 | COPY ./frontend ./ 6 | COPY ./frontend/.env.docker .env 7 | COPY ./packages /movinin/packages 8 | RUN npm install --force 9 | RUN npm run build 10 | 11 | FROM nginx:stable-alpine 12 | WORKDIR /usr/share/nginx/html 13 | RUN rm -rf -- * 14 | COPY --from=build /movinin/frontend/build . 15 | COPY ./frontend/nginx.conf /etc/nginx/conf.d/default.conf 16 | CMD ["nginx", "-g", "daemon off;"] 17 | EXPOSE 80 18 | EXPOSE 443 19 | -------------------------------------------------------------------------------- /frontend/src/lang/booking-property-list.ts: -------------------------------------------------------------------------------- 1 | import LocalizedStrings from 'localized-strings' 2 | import * as langHelper from '@/utils/langHelper' 3 | 4 | const strings = new LocalizedStrings({ 5 | fr: { 6 | REQUIRED_FIELD: 'Veuillez renseigner le champ : ', 7 | REQUIRED_FIELDS: 'Veuillez renseigner les champs : ', 8 | }, 9 | en: { 10 | REQUIRED_FIELD: 'Please fill in the field: ', 11 | REQUIRED_FIELDS: 'Please fill in the fields: ', 12 | }, 13 | }) 14 | 15 | langHelper.setLanguage(strings) 16 | export { strings } 17 | -------------------------------------------------------------------------------- /admin/src/components/InfoBox.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Info as InfoIcon } from '@mui/icons-material' 3 | 4 | import '@/assets/css/info-box.css' 5 | 6 | interface InfoBoxProps { 7 | className?: string 8 | value: string 9 | } 10 | 11 | const InfoBox = ({ className, value }: InfoBoxProps) => ( 12 |
13 | 14 | {value} 15 |
16 | ) 17 | 18 | export default InfoBox 19 | -------------------------------------------------------------------------------- /backend/src/controllers/ipinfoController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express' 2 | import * as ipinfoHelper from '../utils/ipinfoHelper' 3 | 4 | /** 5 | * Returns ISO 2 country code from IP. 6 | * 7 | * @async 8 | * @param {Request} req 9 | * @param {Response} res 10 | * @returns {unknown} 11 | */ 12 | export const getCountryCode = async (req: Request, res: Response) => { 13 | const clientIp = ipinfoHelper.getClientIp(req) 14 | const countryCode = await ipinfoHelper.getCountryCode(clientIp) 15 | res.json(countryCode) 16 | } 17 | -------------------------------------------------------------------------------- /admin/src/components/scheduler/positionManger/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react' 2 | 3 | export type PositionManagerState = { 4 | renderedSlots: { [day: string]: { [resourceId: string]: { [eventId: string]: number } } }; 5 | }; 6 | 7 | type PositionManagerProps = { 8 | setRenderedSlot(day: string, eventId: string, position: number, resourceId?: string): void; 9 | }; 10 | 11 | export const PositionContext = createContext({ 12 | renderedSlots: {}, 13 | setRenderedSlot: () => {}, 14 | }) 15 | -------------------------------------------------------------------------------- /backend/src/routes/stripeRoutes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import routeNames from '../config/stripeRoutes.config' 3 | import * as stripeController from '../controllers/stripeController' 4 | 5 | const routes = express.Router() 6 | 7 | routes.route(routeNames.createCheckoutSession).post(stripeController.createCheckoutSession) 8 | routes.route(routeNames.checkCheckoutSession).post(stripeController.checkCheckoutSession) 9 | routes.route(routeNames.createPaymentIntent).post(stripeController.createPaymentIntent) 10 | 11 | export default routes 12 | -------------------------------------------------------------------------------- /frontend/src/assets/css/view-on-map-button.css: -------------------------------------------------------------------------------- 1 | .view-on-map { 2 | position: absolute; 3 | top: 10px; 4 | right: 10px; 5 | z-index: 10000; 6 | /* background-color: #062638; */ 7 | background-color: #1a1a1a; 8 | color: #fff; 9 | border: 0; 10 | padding: 5px 10px; 11 | display: flex; 12 | flex-direction: row; 13 | border-radius: 5px; 14 | cursor: pointer; 15 | } 16 | 17 | .view-on-map img { 18 | max-width: 20px; 19 | max-height: 20px; 20 | margin-right: 2px; 21 | } 22 | 23 | .view-on-map span { 24 | margin-top: 2px; 25 | } 26 | -------------------------------------------------------------------------------- /frontend/src/pages/Agencies.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Layout from '@/components/Layout' 3 | import AgencyList from '@/components/AgencyList' 4 | import Footer from '@/components/Footer' 5 | 6 | import '@/assets/css/agencies.css' 7 | 8 | const Agencies = () => { 9 | const onLoad = () => { 10 | } 11 | 12 | return ( 13 | 14 |
15 | 16 |
17 |