@proca/widget
Version:
Proca is an open-source campaign toolkit designed to empower activists and organisations in their digital advocacy efforts. It provides a flexible and customisable platform for creating and managing online petitions, email campaigns, and other forms of di
179 lines (157 loc) • 5.24 kB
JavaScript
import React, { useEffect, useState, useMemo } from "react";
import useData from "@hooks/useData";
import { get } from "@lib/urlparser";
import TextField from "@components/TextField";
import { useTranslation } from "react-i18next";
import useGeoLocation from "react-ipgeolocation";
import { useCampaignConfig } from "@hooks/useConfig";
import Alert from "@material-ui/lab/Alert";
import { useCountryFlag, flag } from "react-emoji-flag";
import { allCountries } from "@lib/i18n";
//import countriesJson from "../data/countries.json";
import countriesJson from "../../data/eu27.json";
export const addMissingCountries = (countries, compare) => {
const alreadyHave = {};
countries.reduce((a, c) => {
a[c.iso] = true;
return a;
}, alreadyHave);
let others = [];
for (const [code, label] of Object.entries(allCountries)) {
if (!(code in alreadyHave)) {
others.push({ iso: code, name: label });
}
}
others.sort((a, b) => compare(a.name, b.name));
return countries.filter(({ iso }) => iso !== "ZZ").concat(others);
};
const addAllCountries = () => {
const d = [];
for (const [code, label] of Object.entries(allCountries)) {
d.push({ iso: code, name: label });
}
return d;
};
/*const iso = (list) => {
let d = [];
list.map((country) => d.push(country.iso));
return d;
};*/
const addCountries = list => {
let d = [];
list.map(country => {
country !== "ZZ" &&
d.push({ iso: country, name: allCountries[country] || "" });
return null;
});
return d;
};
const Country = props => {
const config = useCampaignConfig();
const { t } = useTranslation();
const [_countries, setCountries] = useState([]);
const [, setData] = useData();
useCountryFlag({ className: "country-flag" });
const countries = useMemo(() => {
let countries = [];
if (props.countries) {
countries = Object.keys(props.countries).map(iso => ({
iso: iso.toUpperCase(),
name: props.countries[iso] || allCountries[iso],
}));
} else {
countries = addCountries(countriesJson, t);
}
const compare = new Intl.Collator(config.lang.substring(0, 2).toLowerCase())
.compare;
countries.sort((a, b) => compare(a.name, b.name));
if (config.component.country?.all === true) {
countries = addAllCountries();
}
if (config.component.country?.other !== false) {
countries.push({ iso: "ZZ", name: t("Other") });
}
return countries;
}, [
config.component.country?.all,
config.component.country?.other,
config.lang,
props.countries,
props.other,
t,
]);
const { setValue, getValues } = props.form;
let defaultCountry = get("country"); //fetch from the url if set
if (
(!defaultCountry && typeof config.component.country === "string") ||
typeof config.component.register?.field?.country === "string"
) {
defaultCountry =
config.component.country || config.component.register?.field?.country;
if (typeof defaultCountry === "string")
defaultCountry = defaultCountry.toUpperCase();
}
if (getValues("country")) {
defaultCountry = getValues("country");
}
const location = useGeoLocation({
api: "https://country.proca.foundation",
country: defaultCountry,
});
const switchCountry = e => {
setData("country", e.target.value);
};
const countriesLength = _countries.length;
useEffect(() => {
const country = getValues("country") || "";
if (location.country === country && countriesLength !== 0) return;
if (location.country && (!country || typeof country !== "string")) {
if (!countries.find(d => d.iso === location.country)) {
console.log("visitor from ", location?.country, "but not on our list");
countries.unshift({
iso: location.country,
name: allCountries[location.country] || t("Other"),
});
// location.country = countries.find((d) => d.iso === "ZZ") ? "ZZ" : ""; // if "other" exists, set it
}
setCountries(countries);
if (!location.country) return; // not sure how it can happen, remove?
setValue("country", location.country);
setData("country", country);
} else {
// geoLocation doesn't work
setCountries(countries);
}
}, [location, getValues, countries, setValue, setData, t, countriesLength]);
// useEffect(() => {
// register({ name: "country" });
// }, [register]);
if (props.list === false) return null;
// Windows doesn't support flag emojis
return (
<div className="country-flag">
<TextField
required={props.required}
select
name={props.name || "country"}
onChange={switchCountry}
label={t("Country")}
form={props.form}
SelectProps={{
native: true,
}}
>
<option key="" value="" />
{_countries.map(option => (
<option key={option.iso} value={option.iso}>
{flag(option.iso)} {option.name}
</option>
))}
</TextField>
{config.component.country === false && !defaultCountry && (
<Alert severity="info">{t("target.country.undefined")}</Alert>
)}
</div>
);
};
export default Country;