Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I18n Routing #189

Draft
wants to merge 2 commits into
base: react-intl
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 27 additions & 39 deletions packages/react-app/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import { Switch, Redirect, Route } from "react-router-dom";
import { Switch, Route } from "react-router-dom";
import { Web3Provider, StaticJsonRpcProvider, InfuraProvider } from "@ethersproject/providers";
import "./App.css";
import Web3Modal from "web3modal";
import WalletConnectProvider from "@walletconnect/web3-provider";
import { useUserAddress } from "eth-hooks";
import axios from "axios";
import { useIntl } from "react-intl";
import { useUserProvider } from "./hooks";
import { Header, ColorModeSwitcher } from "./components";
import { INFURA_ID, SERVER_URL as serverUrl } from "./constants";
import {
BuilderListView,
ChallengeDetailView,
BuilderProfileView,
SubmissionReviewView,
HomeView,
ActivityView,
} from "./views";
import { USER_ROLES } from "./helpers/constants";
import { SUPPORTED_LANGS, USER_ROLES } from "./helpers/constants";
import { providerPromiseWrapper } from "./helpers/blockchainProviders";
import BlockchainProvidersContext from "./contexts/blockchainProvidersContext";
import SiteFooter from "./components/SiteFooter";
import Routes from "./Routes";
import useUrlLang from "./hooks/useUrlLang";

// 😬 Sorry for all the console logging
const DEBUG = true;
Expand All @@ -41,7 +36,7 @@ const web3Modal = new Web3Modal({
},
});

function App() {
function App({ setLocale }) {
const [providers, setProviders] = useState({
mainnet: { provider: null, isReady: false },
local: { provider: null, isReady: false },
Expand Down Expand Up @@ -165,6 +160,12 @@ function App() {
}
}, [address, fetchUserData]);

const intl = useIntl();
const { lang: urlLang } = useUrlLang();
if (urlLang !== intl.locale) {
setLocale(urlLang);
}

return (
<BlockchainProvidersContext.Provider value={providers}>
<div className="App">
Expand All @@ -179,41 +180,28 @@ function App() {
setUserRole={setUserRole}
/>
<Switch>
<Route exact path="/">
<HomeView connectedBuilder={connectedBuilder} userProvider={userProvider} />
</Route>
<Route exact path="/portfolio">
{address && <Redirect to={"/builders/" + address} />}
</Route>
<Route path="/builders" exact>
<BuilderListView serverUrl={serverUrl} mainnetProvider={mainnetProvider} userRole={userRole} />
</Route>
<Route path="/builders/:builderAddress">
<BuilderProfileView
<Routes
connectedBuilder={connectedBuilder}
userProvider={userProvider}
address={address}
serverUrl={serverUrl}
mainnetProvider={mainnetProvider}
userRole={userRole}
fetchUserData={fetchUserData}
loadWeb3Modal={loadWeb3Modal}
/>
<Route path={`/:lang(${SUPPORTED_LANGS.join("|")})`}>
<Routes
connectedBuilder={connectedBuilder}
userProvider={userProvider}
address={address}
serverUrl={serverUrl}
mainnetProvider={mainnetProvider}
address={address}
userRole={userRole}
userProvider={userProvider}
fetchUserData={fetchUserData}
/>
</Route>
<Route path="/challenge/:challengeId">
<ChallengeDetailView
serverUrl={serverUrl}
address={address}
userProvider={userProvider}
userRole={userRole}
loadWeb3Modal={loadWeb3Modal}
/>
</Route>
{/* ToDo: Protect this route on the frontend? */}
<Route path="/submission-review" exact>
<SubmissionReviewView userProvider={userProvider} mainnetProvider={mainnetProvider} />
</Route>
<Route path="/activity" exact>
<ActivityView />
</Route>
</Switch>
<ColorModeSwitcher />
</div>
Expand Down
68 changes: 68 additions & 0 deletions packages/react-app/src/Routes.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import {
ActivityView,
BuilderListView,
BuilderProfileView,
ChallengeDetailView,
HomeView,
SubmissionReviewView,
} from "./views";
import useUrlLang from "./hooks/useUrlLang";

const Routes = ({
connectedBuilder,
userProvider,
address,
serverUrl,
mainnetProvider,
userRole,
fetchUserData,
loadWeb3Modal,
}) => {
const { langUrlPrefix, path } = useUrlLang();
// INFO: pathPrefix is the path without trailing `/`
const pathPrefix = path.replace(/\/$/, "");

return (
<Switch>
<Route exact path={path}>
<HomeView connectedBuilder={connectedBuilder} userProvider={userProvider} />
</Route>
<Route exact path={`${pathPrefix}/portfolio`}>
{address && <Redirect to={`${langUrlPrefix}/builders/${address}`} />}
</Route>
<Route path={`${pathPrefix}/builders`} exact>
<BuilderListView serverUrl={serverUrl} mainnetProvider={mainnetProvider} userRole={userRole} />
</Route>
<Route path={`${pathPrefix}/builders/:builderAddress`}>
<BuilderProfileView
serverUrl={serverUrl}
mainnetProvider={mainnetProvider}
address={address}
userRole={userRole}
userProvider={userProvider}
fetchUserData={fetchUserData}
/>
</Route>
<Route path={`${pathPrefix}/challenge/:challengeId`}>
<ChallengeDetailView
serverUrl={serverUrl}
address={address}
userProvider={userProvider}
userRole={userRole}
loadWeb3Modal={loadWeb3Modal}
/>
</Route>
{/* ToDo: Protect this route on the frontend? */}
<Route path={`${pathPrefix}/submission-review`} exact>
<SubmissionReviewView userProvider={userProvider} mainnetProvider={mainnetProvider} />
</Route>
<Route path={`${pathPrefix}/activity`} exact>
<ActivityView />
</Route>
</Switch>
);
};

export default Routes;
6 changes: 4 additions & 2 deletions packages/react-app/src/components/Account.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { FormattedMessage } from "react-intl";
import QRPunkBlockie from "./QrPunkBlockie";
import useDisplayAddress from "../hooks/useDisplayAddress";
import useCustomColorModes from "../hooks/useCustomColorModes";
import useUrlLang from "../hooks/useUrlLang";
import { ellipsizedAddress } from "../helpers/strings";
import { USER_ROLES } from "../helpers/constants";
import HeroIconUser from "./icons/HeroIconUser";
Expand Down Expand Up @@ -80,6 +81,7 @@ export default function Account({
const openPopover = () => setIsPopoverOpen(true);
const closePopover = () => setIsPopoverOpen(false);
const { primaryFontColor, secondaryFontColor, dividerColor } = useCustomColorModes();
const { langUrlPrefix } = useUrlLang();

if (!userRole && isWalletConnected) {
return <Spinner />;
Expand Down Expand Up @@ -115,7 +117,7 @@ export default function Account({
const accountMenu = address && (
<LinkBox>
<Flex align="center">
<LinkOverlay as={NavLink} to="/portfolio">
<LinkOverlay as={NavLink} to={`${langUrlPrefix}/portfolio`}>
<QRPunkBlockie withQr={false} address={address.toLowerCase()} w={9} borderRadius={6} />
</LinkOverlay>
<Box ml={4}>
Expand All @@ -138,7 +140,7 @@ export default function Account({
description: (
<>
Visit{" "}
<Link href="/portfolio" textDecoration="underline">
<Link href={`${langUrlPrefix}/portfolio`} textDecoration="underline">
your portfolio
</Link>{" "}
to start building
Expand Down
4 changes: 2 additions & 2 deletions packages/react-app/src/components/ChallengeExpandedCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const ChallengeExpandedCard = ({
overflow="hidden"
>
<Image
src="assets/bgBanner_joinBgClouds.svg"
src="/assets/bgBanner_joinBgClouds.svg"
position="absolute"
top={{ base: "6%", lg: "5%" }}
left={{ base: "4%", lg: "auto" }}
Expand All @@ -118,7 +118,7 @@ const ChallengeExpandedCard = ({
minH={{ base: "md", lg: "lg" }}
>
<Center position="relative" mt={{ base: 2, lg: 8 }}>
<Image src="assets/bgBanner_JoinBG.svg" w="820px" />
<Image src="/assets/bgBanner_JoinBG.svg" w="820px" />
</Center>
<Flex justifyContent="space-between" direction={{ base: "column", lg: "row" }}>
<Text mb={4} color="sre.text" textAlign={{ base: "center", lg: "left" }} maxW={{ base: "100%", lg: "35%" }}>
Expand Down
8 changes: 5 additions & 3 deletions packages/react-app/src/components/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { USER_ROLES } from "../helpers/constants";
import { ENVIRONMENT } from "../constants";
import useCustomColorModes from "../hooks/useCustomColorModes";
import HeaderLogo from "./icons/HeaderLogo";
import useUrlLang from "../hooks/useUrlLang";

export default function Header({
injectedProvider,
Expand All @@ -21,6 +22,7 @@ export default function Header({
const { linkColor, bgColor } = useCustomColorModes();
const primaryColorString = useColorModeValue("var(--chakra-colors-gray-700)", "var(--chakra-colors-gray-200)");
const location = useLocation();
const { langUrlPrefix } = useUrlLang();

const isSignerProviderConnected =
injectedProvider && injectedProvider.getSigner && injectedProvider.getSigner()._isSigner;
Expand Down Expand Up @@ -59,7 +61,7 @@ export default function Header({
>
{!isHomepage && (
<Flex shrink={0} mr={9} mt={{ base: userIsRegistered ? 4 : 0, lg: 0 }}>
<NavLink to="/" exact>
<NavLink to={`${langUrlPrefix}/`} exact>
<HeaderLogo maxW="205px" height="auto" />
</NavLink>
</Flex>
Expand All @@ -78,7 +80,7 @@ export default function Header({
{userRole && USER_ROLES.anonymous !== userRole && (
<chakra.li key="/portfolio" color={linkColor} _hover={{ color: primaryColorString }}>
<NavLink
to="/portfolio"
to={`${langUrlPrefix}/portfolio`}
isActive={(match, location) => location.pathname.includes("/builders/")}
activeStyle={{
color: primaryColorString,
Expand All @@ -93,7 +95,7 @@ export default function Header({
<>
<chakra.li key="/builders" color={linkColor} _hover={{ color: primaryColorString }}>
<NavLink
to="/builders"
to={`${langUrlPrefix}/builders`}
exact
activeStyle={{
color: primaryColorString,
Expand Down
5 changes: 4 additions & 1 deletion packages/react-app/src/components/JoinBG.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import axios from "axios";
import { chakra, useToast, Button, Link } from "@chakra-ui/react";
import { FormattedMessage, useIntl } from "react-intl";
import { SERVER_URL as serverUrl } from "../constants";
import useUrlLang from "../hooks/useUrlLang";

const serverPath = "/bg/join";

Expand All @@ -13,6 +14,8 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user
const [joined, setJoined] = useState(false);
const toast = useToast({ position: "top", isClosable: true });

const { langUrlPrefix } = useUrlLang();

const address = connectedBuilder?.id;

const onJoin = async () => {
Expand All @@ -34,7 +37,7 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user
},
{
Link: chunks => (
<Link href="/portfolio" textDecoration="underline">
<Link href={`${langUrlPrefix}/portfolio`} textDecoration="underline">
{chunks}
</Link>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getChallengeInfo } from "../../data/challenges";
import DateWithTooltip from "../DateWithTooltip";
import ChallengeStatusTag from "../ChallengeStatusTag";
import useCustomColorModes from "../../hooks/useCustomColorModes";
import useUrlLang from "../../hooks/useUrlLang";

export const BuilderChallenges = ({
challenges,
Expand All @@ -33,6 +34,7 @@ export const BuilderChallenges = ({
const { primaryFontColor, secondaryFontColor, borderColor, linkColor } = useCustomColorModes();
const intl = useIntl();
const challengeInfo = getChallengeInfo(intl);
const { langUrlPrefix } = useUrlLang();

return (
<>
Expand Down Expand Up @@ -85,7 +87,12 @@ export const BuilderChallenges = ({
return (
<Tr key={challengeId}>
<Td>
<Link as={RouteLink} to={`/challenge/${challengeId}`} fontWeight="bold" color={linkColor}>
<Link
as={RouteLink}
to={`${langUrlPrefix}/challenge/${challengeId}`}
fontWeight="bold"
color={linkColor}
>
{challengeInfo[challengeId].label}
</Link>
</Td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
import { bySocialWeight, socials } from "../../data/socials";
import { USER_ROLES } from "../../helpers/constants";
import { validateSocials } from "../../helpers/validators";
import useUrlLang from "../../hooks/useUrlLang";

const BuilderProfileCardSkeleton = ({ isLoaded, children }) => (
<Skeleton isLoaded={isLoaded}>{isLoaded ? children() : <SkeletonText mt="4" noOfLines={4} spacing="4" />}</Skeleton>
Expand All @@ -61,6 +62,8 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide
const shortAddress = ellipsizedAddress(builder?.id);
const hasEns = ens !== shortAddress;

const { langUrlPrefix } = useUrlLang();

const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");

Expand Down Expand Up @@ -250,7 +253,7 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide
maxW={{ base: "full", lg: "50%", xl: 60 }}
margin="auto"
>
<Link as={RouteLink} to={`/builders/${builder.id}`}>
<Link as={RouteLink} to={`${langUrlPrefix}/builders/${builder.id}`}>
<QRPunkBlockie
withQr={false}
address={builder.id?.toLowerCase()}
Expand Down
Loading