├── public ├── _redirects ├── robots.txt ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── survivetogether-banner.png ├── manifest.json └── index.html ├── src ├── react-app-env.d.ts ├── assets │ ├── survive-together-logo.png │ └── survive-together-logo-inverted-small.png ├── graphql-types │ ├── itemCategory.ts │ ├── district.ts │ ├── generated │ │ ├── ItemCategory.ts │ │ ├── District.ts │ │ ├── InsertNeed.ts │ │ ├── InsertDistributor.ts │ │ ├── City.ts │ │ ├── Need.ts │ │ ├── LatestNeeds.ts │ │ ├── CityByNeeds.ts │ │ └── Distributor.ts │ ├── city.ts │ ├── distributor.ts │ └── need.ts ├── setupTests.ts ├── config.ts ├── App.test.tsx ├── components │ ├── shared │ │ ├── styledComponents.ts │ │ ├── STNotification.tsx │ │ ├── STPageHeader.tsx │ │ ├── STModal.tsx │ │ ├── STInput.tsx │ │ ├── STRequestCard.tsx │ │ ├── STCitySummaryCard.tsx │ │ ├── STSelect.tsx │ │ ├── STPageHeaderWithFilters.tsx │ │ └── STDistributorCard.tsx │ ├── app │ │ ├── AppLayout.tsx │ │ ├── Footer.tsx │ │ └── NavBar.tsx │ ├── contactUsLanguges │ │ ├── ContactUsSinhala.tsx │ │ └── ContactUsEnglish.tsx │ ├── LatestRequests.tsx │ ├── MostRequestedDistricts.tsx │ ├── home │ │ ├── Hero.tsx │ │ └── AreaSelection.tsx │ ├── termsAndConditionsLanguges │ │ ├── TermsAndConditionsEnglish.tsx │ │ └── TermsAndConditionsSinhala.tsx │ ├── aboutUsLanguges │ │ ├── AboutUSEnglish.tsx │ │ └── AboutUsSinhala.tsx │ └── privacyPolicyLanguges │ │ ├── PrivacyPolicyEnglish.tsx │ │ └── PrivacyPolicySinhala.tsx ├── containers │ ├── AboutUs.tsx │ ├── ContactUs.tsx │ ├── PrivacyPolicy.tsx │ ├── TermsAndConditions.tsx │ ├── Districts.jsx │ ├── Distributors.tsx │ ├── CreateRequest.tsx │ ├── Requests.tsx │ ├── Home.tsx │ └── CreateDistributor.tsx ├── store.ts ├── model │ └── area.ts ├── localization │ ├── i18n.ts │ ├── en.ts │ └── si.ts ├── lib │ └── apollo.ts ├── types.ts ├── validations.ts ├── index.tsx ├── index.css ├── helpers │ ├── sharedHelpers.ts │ ├── requestHelpers.ts │ └── distributorHelpers.ts ├── App.tsx └── serviceWorker.ts ├── .eslintignore ├── .sample_env ├── apollo.config.js ├── tsconfig.json ├── .eslintrc.js ├── README.md ├── package.json ├── CONTRIBUTING.md └── .gitignore /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/survivetogether-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/public/survivetogether-banner.png -------------------------------------------------------------------------------- /src/assets/survive-together-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/src/assets/survive-together-logo.png -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules/** 2 | **/dist/** 3 | **/storybook-static/** 4 | **/coverage/** 5 | **/build/** 6 | **/.git/** 7 | **/public/** -------------------------------------------------------------------------------- /src/assets/survive-together-logo-inverted-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeafyCode/survive-together-web/HEAD/src/assets/survive-together-logo-inverted-small.png -------------------------------------------------------------------------------- /.sample_env: -------------------------------------------------------------------------------- 1 | REACT_APP_GRAPHQL_ENDPOINT=http://localhost:8080/v1/graphql 2 | REACT_APP_GRAPHQL_WS_ENDPOINT=wss://localhost:8080/v1/graphql 3 | REACT_APP_COUNTRY_ID=taken_from_the_db 4 | HASURA_GRAPHQL_ADMIN_SECRET=secret 5 | -------------------------------------------------------------------------------- /src/graphql-types/itemCategory.ts: -------------------------------------------------------------------------------- 1 | import { gql } from "apollo-boost"; 2 | 3 | export const ITEM_CATEGORIES = gql` 4 | query ItemCategory { 5 | item_category { 6 | id 7 | name 8 | } 9 | } 10 | `; 11 | -------------------------------------------------------------------------------- /src/graphql-types/district.ts: -------------------------------------------------------------------------------- 1 | import { gql } from "apollo-boost"; 2 | 3 | export const DISTRICT = gql` 4 | query District($where: district_bool_exp) { 5 | district(where: $where) { 6 | name 7 | id 8 | } 9 | } 10 | `; 11 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export const GRAPHQL_ENDPOINT = process.env.REACT_APP_GRAPHQL_ENDPOINT; 2 | export const GRAPHQL_WS_ENDPOINT = process.env.REACT_APP_GRAPHQL_WS_ENDPOINT; 3 | export const SENTRY_DSN = process.env.REACT_APP_SENTRY_DSN; 4 | 5 | export const COUNTRY_ID = process.env.REACT_APP_COUNTRY_ID; 6 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /apollo.config.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | 3 | module.exports = { 4 | client: { 5 | service: { 6 | name: "ST GraphQL Schema", 7 | url: process.env.REACT_APP_GRAPHQL_ENDPOINT, 8 | headers: { 9 | "x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET, 10 | }, 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /src/components/shared/styledComponents.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const STPageContainer = styled.div` 4 | padding: 20px; 5 | `; 6 | 7 | export const STPageContentWrapper = styled.div` 8 | p { 9 | margin-bottom: 13px; 10 | } 11 | `; 12 | 13 | export const STFormArrayRemoveButton = styled.button` 14 | margin-top: 31px; 15 | `; 16 | -------------------------------------------------------------------------------- /src/components/shared/STNotification.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "react-i18next"; 3 | 4 | export const STNotification = () => { 5 | const { t } = useTranslation(); 6 | 7 | return ( 8 |
9 | {t("notificationContent")} 10 |
11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /src/containers/AboutUs.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "react-i18next"; 3 | import { AboutUsEnglish } from "../components/aboutUsLanguges/AboutUSEnglish"; 4 | import { AboutUsSinhala } from "../components/aboutUsLanguges/AboutUsSinhala"; 5 | 6 | export const AboutUs = () => { 7 | const { i18n } = useTranslation(); 8 | 9 | if (i18n.language === "si") { 10 | return ; 11 | } 12 | 13 | return ; 14 | }; 15 | -------------------------------------------------------------------------------- /src/containers/ContactUs.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "react-i18next"; 3 | import { ContactUsSinhala } from "../components/contactUsLanguges/ContactUsSinhala"; 4 | import { ContactUsEnglish } from "../components/contactUsLanguges/ContactUsEnglish"; 5 | 6 | export const ContactUs = () => { 7 | const { i18n } = useTranslation(); 8 | 9 | if (i18n.language === "si") { 10 | return ; 11 | } 12 | 13 | return ; 14 | }; 15 | -------------------------------------------------------------------------------- /src/containers/PrivacyPolicy.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "react-i18next"; 3 | import { PrivacyPolicySinhala } from "../components/privacyPolicyLanguges/PrivacyPolicySinhala"; 4 | import { PrivacyPolicyEnglish } from "../components/privacyPolicyLanguges/PrivacyPolicyEnglish"; 5 | 6 | export const PrivacyPolicy = () => { 7 | const { i18n } = useTranslation(); 8 | 9 | if (i18n.language === "si") { 10 | return ; 11 | } 12 | 13 | return ; 14 | }; 15 | -------------------------------------------------------------------------------- /src/containers/TermsAndConditions.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "react-i18next"; 3 | import { TermsAndConditionsEnglish } from "../components/termsAndConditionsLanguges/TermsAndConditionsEnglish"; 4 | import { TermsAndConditionsSinhala } from "../components/termsAndConditionsLanguges/TermsAndConditionsSinhala"; 5 | 6 | export const TermsAndConditions = () => { 7 | const { i18n } = useTranslation(); 8 | 9 | if (i18n.language === "si") { 10 | return ; 11 | } 12 | 13 | return ; 14 | }; 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "react" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/store.ts: -------------------------------------------------------------------------------- 1 | import { createStore, createTypedHooks } from "easy-peasy"; 2 | import { AreaModel, area } from "./model/area"; 3 | 4 | export interface StoreModel { 5 | area: AreaModel; 6 | } 7 | 8 | const model: StoreModel = { 9 | area, 10 | }; 11 | 12 | export const store = createStore(model); 13 | 14 | const typedHooks = createTypedHooks(); 15 | 16 | // We export the hooks from our store as they will contain the 17 | // type information on them 18 | export const { useStoreActions } = typedHooks; 19 | export const { useStoreDispatch } = typedHooks; 20 | export const { useStoreState } = typedHooks; 21 | -------------------------------------------------------------------------------- /src/graphql-types/generated/ItemCategory.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | // @generated 4 | // This file was automatically generated and should not be edited. 5 | 6 | // ==================================================== 7 | // GraphQL query operation: ItemCategory 8 | // ==================================================== 9 | 10 | export interface ItemCategory_item_category { 11 | __typename: "item_category"; 12 | id: any; 13 | name: string; 14 | } 15 | 16 | export interface ItemCategory { 17 | /** 18 | * fetch data from the table: "item_category" 19 | */ 20 | item_category: ItemCategory_item_category[]; 21 | } 22 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Survive Together", 3 | "name": "Survive Together Disaster Management App", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "android-chrome-192x192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "android-chrome-512x512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#00D4BB", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/shared/STPageHeader.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useTranslation } from "react-i18next"; 3 | 4 | interface STPageHeaderProps { 5 | title: string; 6 | subTitle: string; 7 | } 8 | 9 | export const STPageHeader = ({ title, subTitle }: STPageHeaderProps) => { 10 | const { t } = useTranslation(); 11 | 12 | return ( 13 |
14 |
15 |
16 |

{t(`${title}InputLabel`)}

17 |

{t(`${subTitle}InputLabel`)}

18 |
19 |
20 |
21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /src/model/area.ts: -------------------------------------------------------------------------------- 1 | import { Action, action } from "easy-peasy"; 2 | import { STSelectOption } from "../types"; 3 | 4 | export interface AreaModel { 5 | district?: STSelectOption; 6 | city?: STSelectOption; 7 | setDistrict: Action; 8 | setCity: Action; 9 | } 10 | 11 | export const area: AreaModel = { 12 | district: undefined, 13 | city: undefined, 14 | setDistrict: action((state, payload) => { 15 | // eslint-disable-next-line no-param-reassign 16 | state.district = payload; 17 | }), 18 | setCity: action((state, payload) => { 19 | // eslint-disable-next-line no-param-reassign 20 | state.city = payload; 21 | }), 22 | }; 23 | -------------------------------------------------------------------------------- /src/graphql-types/generated/District.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | // @generated 4 | // This file was automatically generated and should not be edited. 5 | 6 | import { district_bool_exp } from "./graphql-global-types"; 7 | 8 | // ==================================================== 9 | // GraphQL query operation: District 10 | // ==================================================== 11 | 12 | export interface District_district { 13 | __typename: "district"; 14 | name: string; 15 | id: any; 16 | } 17 | 18 | export interface District { 19 | /** 20 | * fetch data from the table: "district" 21 | */ 22 | district: District_district[]; 23 | } 24 | 25 | export interface DistrictVariables { 26 | where?: district_bool_exp | null; 27 | } 28 | -------------------------------------------------------------------------------- /src/localization/i18n.ts: -------------------------------------------------------------------------------- 1 | import i18n from "i18next"; 2 | import { initReactI18next } from "react-i18next"; 3 | import LanguageDetector from "i18next-browser-languagedetector"; 4 | import { en } from "./en"; 5 | import { si } from "./si"; 6 | 7 | const resources = { 8 | en, 9 | si, 10 | }; 11 | 12 | i18n 13 | .use(LanguageDetector) 14 | .use(initReactI18next) // passes i18n down to react-i18next 15 | .init({ 16 | resources, 17 | fallbackLng: "si", 18 | lng: "si", // Make it default since we serve only sri lanka now 19 | saveMissing: true, 20 | 21 | keySeparator: false, // we do not use keys in form messages.welcome 22 | 23 | interpolation: { 24 | escapeValue: false, // react already safes from xss 25 | }, 26 | }); 27 | 28 | export default i18n; 29 | -------------------------------------------------------------------------------- /src/components/app/AppLayout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import { NavBar } from "./NavBar"; 4 | import { Footer } from "./Footer"; 5 | import { STNotification } from "../shared/STNotification"; 6 | 7 | const AppContainer = styled.div` 8 | display: flex; 9 | flex-direction: column; 10 | min-height: 100vh; 11 | `; 12 | 13 | const AppContent = styled.div` 14 | flex-grow: 1; 15 | `; 16 | 17 | interface AppLayoutProps { 18 | children: React.ReactNode; 19 | } 20 | 21 | export const AppLayout = ({ children }: AppLayoutProps) => { 22 | return ( 23 | 24 | 25 | 26 | 27 | {children} 28 | 29 |