diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
deleted file mode 100644
index fbbfc779..00000000
--- a/.gitlab/CODEOWNERS
+++ /dev/null
@@ -1 +0,0 @@
-* @arturas.mickiewicz @szymon.skorupinski.need4deed
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
deleted file mode 100644
index 316dc672..00000000
--- a/.gitlab/issue_templates/Bug.md
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-## Bug Report
-
-### Describe the Bug
-
-
-
-### Steps to Reproduce
-
-1.
-
-### Expected Behavior
-
-
-
-### Actual Behavior
-
-
-
-### Environment
-
-
-
-- Browser:
-- Commit hash:
-
-### Screenshots
-
-
-
-### Proposed Solution
-
-
-
-### The impact of the bug
-
-
-
-
diff --git a/.gitlab/issue_templates/Feature_request.md b/.gitlab/issue_templates/Feature_request.md
deleted file mode 100644
index 36481956..00000000
--- a/.gitlab/issue_templates/Feature_request.md
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-## Feature Request
-
-### Feature Description
-
-
-
-### What's the impact of the feature on the project
-
-
-
-### Proposed Solution
-
-
-
-### Additional Context
-
-
-
-### Acceptance criteria
-
-
-
-
diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md
deleted file mode 100644
index 60775bbb..00000000
--- a/.gitlab/merge_request_templates/Default.md
+++ /dev/null
@@ -1,28 +0,0 @@
-### What does this MR do?
-
-e.g. Fixes memory leak in data processing function by properly closing file handles.
-
-### Type of Change
-
-e.g. Bug fix (non-breaking change which fixes an issue)
-
-### Related Issue(s)
-
-e.g.
-
-- Fixes #123
-
-## Checklist
-
-### Documentation Updates
-
-- [ ] My code needs changes in the documentation
-
-### Code Quality
-
-- [ ] My code follows the project's style guidelines
-
-### Testing
-
-- [ ] I have added unit tests for the fixed scenario
-- [ ] The change needs end to end test coverage
diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md
index 2eba94c0..a5f21475 100644
--- a/CONTRIBUTE.md
+++ b/CONTRIBUTE.md
@@ -26,22 +26,22 @@ This project and everyone participating in it is governed by our [Code of Conduc
### Your First Code Contribution
-Unsure where to begin contributing? You can start by looking through `good-first-issue` labeled [issues](https://gitlab.com/need4deed/website/-/issues/?label_name%5B%5D=good-first-issue)
+Unsure where to begin contributing? You can start by looking through `good-first-issue` labeled [issues](https://github.com/need4deed-org/website/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22)
### First Merge Request
Step 1: Fork the Repository
-1. Go to the our repository: [https://gitlab.com/need4deed/website](https://gitlab.com/need4deed/website).
+1. Go to the our repository: [https://github.com/need4deed-org/website](https://github.com/need4deed-org/website).
1. Click the **Fork** button in the top-right corner.
-1. Choose where to fork the repository (usually your own GitLab account).
+1. Choose where to fork the repository (usually your own GitHub account).
Step 2: Clone Your Forked Repository
-1. Go to your forked repository (e.g., `https://gitlab.com/your-username/website`).
+1. Go to your forked repository (e.g., `https://github.com/your-username/website`).
1. Click the **Clone** button and copy it e.g. with HTTPS URL.
```bash
- git clone https://gitlab.com/your-username/website.git
+ git clone git@github.com:need4deed-org/website.git
```
1. Navigate into the cloned repository:
@@ -53,7 +53,7 @@ Step 3: Add the Original Repository as a Remote
1. Add the original repository as a remote called `upstream`:
```bash
- git remote add upstream https://gitlab.com/need4deed/website.git
+ git remote add upstream https://github.com/need4deed-org/website.git
```
1. Verify the remotes:
@@ -70,7 +70,7 @@ Step 3: Add the Original Repository as a Remote
```bash
git checkout -b your-branch-name
```
- The branch should titled be your_nick-feature-title
+ The branch should titled be issue#-your_nick-feature-title, like `123-johndoe-update-readme`
Step 4: Commit and Push Your Changes
@@ -87,15 +87,16 @@ Step 4: Commit and Push Your Changes
git push origin your-branch-name
```
-Step 5: Create a merge request
+Step 5: Create a pull request (PR)
-1. Go to your forked repository on GitLab: `https://gitlab.com/your-username/website`.
-1. Click on **Merge Requests** in the left sidebar.
-1. Click **New Merge Request**.
-1. Select your branch (`your-branch-name`) as the **Source Branch** and `main` as the **Target Branch**.
-1. Fill in the Merge Request template
-1. Click **Create Merge Request**.
-1. Let us know about the awaiting review!
+1. Go to your forked repository on GitHub: `https://github.com/your-username/website`.
+2. Click on **Pull requests** in the left sidebar.
+3. Click **New pull request**.
+4. Select your branch (`your-branch-name`) on the right and make sure `develop` is on the left.
+5. Click **Create pull request**.
+6. Fill in the Pull Request template
+7. Click **Create pull request**.
+8. Let us know about the awaiting review!
### Reporting Bugs
@@ -103,15 +104,15 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
#### Before Submitting A Bug Report
-- Please check [check](https://gitlab.com/need4deed/website/-/issues/?sort=created_date&state=opened&label_name%5B%5D=Any&first_page_size=20) if the problem has already been reported.
+- Please check [already reported bugs](https://github.com/need4deed-org/website/issues?q=is%3Aissue%20state%3Aopen%20type%3ABug) if the problem has already been reported.
#### How Do I Submit A Bug Report?
-Bugs are tracked as [GitLab issues](https://gitlab.com/need4deed/website/-/issues). Create a bug issue. All the necesary info should be in the bug template.
+Bugs are tracked as [GitHub issues](https://github.com/need4deed-org/website/issues). Create a bug issue. All the necessary info should be in the bug template.
### Suggesting features
-Feature suggestions are also tracked as [GitLab issues](https://gitlab.com/need4deed/website/-/issues). Please refer to the feature template.
+Feature suggestions are also tracked as [GitHub issues](https://github.com/need4deed-org/website/issues). Please refer to the feature template.
## Styleguides
@@ -128,6 +129,8 @@ Feature suggestions are also tracked as [GitLab issues](https://gitlab.com/need4
- 🐛 `:bug:` when fixing a bug
- 🔥 `:fire:` when removing code or files
+Please keep commits reasonably scoped, e.g. a single commit containing all the diffs is hard to comprehend.
+
### JavaScript Styleguide
Please refer to the linter.
@@ -141,7 +144,7 @@ By contributing, you agree that your contributions will be licensed under its [C
Don't hesitate to reach out if you have any questions! You can:
- Open an issue
-- Reach out to [@maintainer](https://gitlab.com/szymon.skorupinski.need4deed])
-- Join our Slack (please request an access h4ck@need4deed.org)
+- Reach out to [@need4deed](https://github.com/need4deed)
+- Join our Slack (please request an access dev@need4deed.org)
Any contributions are welcome! 🙏
diff --git a/README.md b/README.md
index f3383b04..5d29cfe1 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ The number of people fleeing conflict zones, persecution and human rights violat
## Equal opportunities
-People living under destitute life conditions should be given equal opportunities. The latter includes underserved individuals and groups affected by forced migration.
+People living under destitute life conditions should be given equal opportunities. The latter includes undeserved individuals and groups affected by forced migration.
## Responsibility
@@ -33,17 +33,17 @@ Applying technology in the effort to support underserved communities is a key va
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
## Background
+
We use simple react/vite app for landing page, aka [website], which is being served from files on S3 using Amplify
we're also developing a PWA on nextjs for automation of need4deed business processes, this is fe repo. also we use separate repo sdk mostly for sharing of types between fron and backend.
also we plan merging our landing page into the app so in the end there should be frontend, backend, and sdk.
so the website is now kind of frozen in terms of development. it still operates along with legacy backend before we launch the app with the new backend.
-
## Step 1: Fork the Repository
1. Go to the our repository: [https://github.com/need4deed-org/website](https://github.com/need4deed-org/website).
1. Click the **Fork** button in the top-right corner.
-1. Choose where to fork the repository (usually your own GitLab account).
+1. Choose where to fork the repository (usually your own GitHub account).
See [CONTRIBUTE.md](CONTRIBUTE.md) for the next steps and detailed contribution guidelines.
@@ -65,7 +65,7 @@ See [CONTRIBUTE.md](CONTRIBUTE.md) for the next steps and detailed contribution
1. Clone the repository
```bash
-git clone git@gitlab.com:need4deed/website.git
+git clone git@github.com:need4deed-org/website.git
```
2. Install dependencies
@@ -115,6 +115,6 @@ This project is licensed under the Common Clause and the MIT License - see the [
## Support 💬
-- Create an [Issue](https://gitlab.com/need4deed/website/-/issues)
+- Create an [Issue](https://github.com/need4deed-org/website/issues)
- Join our Slack - ask as for an inivatation
- Email: h4ck@need4deed.org
diff --git a/src/App.tsx b/src/App.tsx
index cbf2a882..caf8d22c 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -165,6 +165,10 @@ function App() {
path={`/${Subpages.OPPORTUNITY_FORM}`}
element={}
/>
+ }
+ />
}
@@ -177,6 +181,10 @@ function App() {
path={`/${Subpages.VOLUNTEER_FORM}`}
element={}
/>
+ }
+ />
}
diff --git a/src/components/OpportunityCards/Cards.tsx b/src/components/OpportunityCards/Cards.tsx
index 05345b2a..9bdb2a6c 100644
--- a/src/components/OpportunityCards/Cards.tsx
+++ b/src/components/OpportunityCards/Cards.tsx
@@ -3,18 +3,20 @@ import { useTranslation } from "react-i18next";
import styled from "styled-components";
import { OpportunityParams, ScreenTypes } from "../../config/types";
import useOpportunities from "../../hooks/api/useOpportunities";
+import useScreenType from "../../hooks/useScreenType";
import Announcement from "../Announcement";
+import PaginatedGrid from "../core/paginatedGrid/PaginatedGrid";
+import OpportunityCard from "../VolunteeringOpportunities/OpportunityCard";
import OpportunityCardPopup from "../VolunteeringOpportunities/OpportunityCardPopup";
+import {
+ Opportunity,
+ OpportunityApi,
+} from "../VolunteeringOpportunities/types";
import {
CategoryTitle,
getIconName,
getMappedOpportunities,
} from "../VolunteeringOpportunities/utils";
-import {
- Opportunity,
- OpportunityApi,
-} from "../VolunteeringOpportunities/types";
-import OpportunityCard from "../VolunteeringOpportunities/OpportunityCard";
import {
extractCardsFilter,
filterOpportunity,
@@ -22,8 +24,6 @@ import {
reduceFilter,
} from "./helpers";
import { CardsFilter, SetFilter } from "./types";
-import PaginatedGrid from "../core/paginatedGrid/PaginatedGrid";
-import useScreenType from "../../hooks/useScreenType";
interface Props extends React.HTMLAttributes {
url: string;
diff --git a/src/components/OpportunityCards/OpportunityCards.tsx b/src/components/OpportunityCards/OpportunityCards.tsx
index 1926df1b..ba91dd6b 100644
--- a/src/components/OpportunityCards/OpportunityCards.tsx
+++ b/src/components/OpportunityCards/OpportunityCards.tsx
@@ -1,16 +1,16 @@
-import { useLocation, useSearchParams } from "react-router-dom";
-import styled from "styled-components";
import { Lang, OpportunityType } from "need4deed-sdk";
-import { useTranslation } from "react-i18next";
import { useState } from "react";
-import Cards from "./Cards";
+import { useTranslation } from "react-i18next";
+import { useLocation, useSearchParams } from "react-router-dom";
+import styled from "styled-components";
import { urlApiOpportunity } from "../../config/constants";
-import OpportunityCardsHeader from "./OpportunityCardsHeader";
-import MapView from "./MapView";
+import Cards from "./Cards";
import Filters from "./Filters/Filters";
import { defaultFilter, FILTER_KEY_LIST } from "./Filters/constants";
-import { CardsFilter } from "./types";
+import MapView from "./MapView";
+import OpportunityCardsHeader from "./OpportunityCardsHeader";
import { deserializeFilters, openFilters, serializeFilters } from "./helpers";
+import { CardsFilter } from "./types";
const OpportunitiesContainer = styled.div`
display: flex;
@@ -90,7 +90,7 @@ export function OpportunityCards() {
{selectedTabIndex === 0 ? (
= {
1: "monday",
@@ -236,7 +236,7 @@ export const extractCardsFilter = (
if (opp.categoryId !== CategoryTitle.ACCOMPANYING)
categoriesSet.add(opp.category);
- opp.locations.forEach((l) => districtSet.add(l));
+ opp.locations?.forEach((l) => districtSet.add(l));
}
putItemToEnd(
diff --git a/src/components/VolunteeringOpportunities/utils.ts b/src/components/VolunteeringOpportunities/utils.ts
index 4a5c451e..98500087 100644
--- a/src/components/VolunteeringOpportunities/utils.ts
+++ b/src/components/VolunteeringOpportunities/utils.ts
@@ -153,7 +153,8 @@ export const getMappedOpportunities = (
opps: OpportunityApi[],
t: TFunction,
) => {
- return opps.map((opp) => mapOpportunity(opp, t));
+ const oppArray = Array.isArray(opps) ? opps : [];
+ return oppArray.map((opp) => mapOpportunity(opp, t));
};
export function getIconName(category: CategoryTitle) {
diff --git a/src/components/forms/AddOpportunity/index.tsx b/src/components/forms/AddOpportunity/index.tsx
index 958b3df0..35345c05 100644
--- a/src/components/forms/AddOpportunity/index.tsx
+++ b/src/components/forms/AddOpportunity/index.tsx
@@ -63,7 +63,7 @@ export default function AddOpportunity() {
const { postRequest } = usePostRequest<
OpportunityParsedData,
Record
- >({ url: `${urlApi}/opportunity/` });
+ >({ url: `${urlApi}/api/opportunity/legacy` });
const formOpportunity = useForm({
defaultValues: {
diff --git a/src/components/forms/BecomeVolunteer/index.tsx b/src/components/forms/BecomeVolunteer/index.tsx
index 44da6a47..0ab8fabc 100644
--- a/src/components/forms/BecomeVolunteer/index.tsx
+++ b/src/components/forms/BecomeVolunteer/index.tsx
@@ -48,7 +48,7 @@ export default function BecomeVolunteer() {
const { postRequest } = usePostRequest<
VolunteerParsedData,
Record
- >({ url: `${urlApi}/volunteer/` });
+ >({ url: `${urlApi}/api/volunteer/legacy` });
const opportunity: OpportunityInfo = {
id: opportunityParams.get("id") || "",
diff --git a/src/components/forms/index.tsx b/src/components/forms/index.tsx
index 4c6512b2..f0c4ae10 100644
--- a/src/components/forms/index.tsx
+++ b/src/components/forms/index.tsx
@@ -1,22 +1,16 @@
-import AddOpportunity from "./AddOpportunity";
-import BecomeVolunteer from "./BecomeVolunteer";
+import { Lang } from "need4deed-sdk";
+import { useTranslation } from "react-i18next";
+import { getExternalUrl } from "../../utils";
import { FormType } from "./types";
interface Props {
form: FormType;
}
-function render(form: FormType) {
- switch (form) {
- case FormType.VOLUNTEER:
- return ;
- case FormType.OPPORTUNITY:
- return ;
- default:
- return null;
- }
-}
-
export default function Form({ form }: Props) {
- return render(form);
+ const { i18n } = useTranslation();
+
+ const to = getExternalUrl(i18n.language as Lang, form);
+ window.location.replace(to);
+ return null;
}
diff --git a/src/config/constants.ts b/src/config/constants.ts
index 20ae907b..40c6e2ab 100644
--- a/src/config/constants.ts
+++ b/src/config/constants.ts
@@ -1,14 +1,15 @@
-export const urlApi =
- import.meta.env.VITE_API_URL ?? "http://localhost:8000/api";
+export const urlApi = import.meta.env.VITE_API_URL ?? "http://localhost:8000";
export const googleAnalyticsId = "G-5RG5NQ12YS";
-export const urlApiVolunteer = `${urlApi}/volunteer/`;
-export const urlApiOpportunity = `${urlApi}/opportunity/`;
-export const urlApiAuthEmailDomain = `${urlApi}/auth-email-domain/`;
-export const urlApiTestimonial = `${urlApi}/testimonial/`;
-export const urlApiEvent = `${urlApi}/event/`;
+export const urlApiVolunteer = `${urlApi}/api/volunteer`;
+export const urlApiOpportunity = `${urlApi}/api/opportunity`;
+export const urlApiAuthEmailDomain = `${urlApi}/api/auth-email-domain/`;
+export const urlApiTestimonial = `${urlApi}/api/testimonial/`;
+export const urlApiEvent = `${urlApi}/api/event/`;
export const CLOUDFRONT_URL = "https://d2nwrdddg8skub.cloudfront.net/images";
+export const EXTERNAL_OPPORTUNITY_FORM = `${urlApi}/de/forms/opportunity`;
+export const EXTERNAL_VOLUNTEER_FORM = `${urlApi}/de/forms/volunteer`;
const positives = ["1", "YES", "Yes", "yes", "TRUE", "True", "true"];
diff --git a/src/utils/index.spec.tsx b/src/utils/index.spec.tsx
index 7b964fe1..f39cbbcf 100644
--- a/src/utils/index.spec.tsx
+++ b/src/utils/index.spec.tsx
@@ -2,9 +2,11 @@ import { render } from "@testing-library/react";
import { Lang } from "need4deed-sdk";
import { RefObject, act, createRef } from "react";
+import { FormType } from "../components/forms/types";
import { OpportunityParams } from "../config/types";
import {
getBaseUrl,
+ getExternalUrl,
getFirstThursdayOfMonth,
getOpportunityImg,
getReadableLocalTime,
@@ -407,4 +409,46 @@ describe("utils", () => {
expect(() => Array.from(range(0, 5, 0))).toThrow(RangeError);
});
});
+
+ describe("getExternalUrl()", () => {
+ describe("Edge Cases / Invalid Inputs", () => {
+ it("should return an empty string if lng is missing", () => {
+ // @ts-expect-error - testing runtime safety
+ expect(getExternalUrl(null, FormType.OPPORTUNITY)).toBe("");
+ });
+
+ it("should return an empty string if type is missing", () => {
+ // @ts-expect-error - testing runtime safety
+ expect(getExternalUrl(Lang.DE, null)).toBe("");
+ });
+ });
+
+ describe("German (DE) - Default Language", () => {
+ it("should return the base URL for OPPORTUNITY in German", () => {
+ const result = getExternalUrl(Lang.DE, FormType.OPPORTUNITY);
+ // Assuming EXTERNAL_OPPORTUNITY_FORM contains "/de/"
+ expect(result).toContain("/de/");
+ expect(result).not.toContain("/en/");
+ });
+
+ it("should return the base URL for VOLUNTEER in German", () => {
+ const result = getExternalUrl(Lang.DE, FormType.VOLUNTEER);
+ expect(result).toContain("/de/");
+ });
+ });
+
+ describe("English (EN) - URL Transformation", () => {
+ it('should replace "/de/" with "/en/" for OPPORTUNITY', () => {
+ const result = getExternalUrl(Lang.EN, FormType.OPPORTUNITY);
+ expect(result).toContain("/en/");
+ expect(result).not.toContain("/de/");
+ });
+
+ it('should replace "/de/" with "/en/" for VOLUNTEER', () => {
+ const result = getExternalUrl(Lang.EN, FormType.VOLUNTEER);
+ expect(result).toContain("/en/");
+ expect(result).not.toContain("/de/");
+ });
+ });
+ });
});
diff --git a/src/utils/index.ts b/src/utils/index.ts
index ce4a09b2..865e0238 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,8 +1,11 @@
import { Lang } from "need4deed-sdk";
import { MutableRefObject } from "react";
+import { FormType } from "../components/forms/types";
import {
CLOUDFRONT_URL,
+ EXTERNAL_OPPORTUNITY_FORM,
+ EXTERNAL_VOLUNTEER_FORM,
n4dLanguageLocalStorageKey,
timeZone,
} from "../config/constants";
@@ -477,3 +480,19 @@ export function getQueryParamLang(): Lang | null {
return Object.values(Lang).includes(lang) ? lang : null;
}
+
+export function getExternalUrl(lng: Lang, type: FormType) {
+ if (!lng || !type) {
+ return "";
+ }
+ const url =
+ type === FormType.OPPORTUNITY
+ ? EXTERNAL_OPPORTUNITY_FORM
+ : EXTERNAL_VOLUNTEER_FORM;
+
+ if (lng === Lang.DE) {
+ return url;
+ }
+
+ return url.replace("/de/", "/en/");
+}