Skip to content

Commit

Permalink
Complete landing page
Browse files Browse the repository at this point in the history
  • Loading branch information
ttbowen committed Sep 23, 2023
1 parent 65eedf1 commit 544e26b
Show file tree
Hide file tree
Showing 17 changed files with 299 additions and 18 deletions.
4 changes: 3 additions & 1 deletion packages/mrwhale-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
"react-dom": "^18.2.0",
"react-hook-form": "^7.46.1",
"react-redux": "^8.1.2",
"react-router-dom": "^6.15.0"
"react-router-dom": "^6.15.0",
"react-visibility-sensor": "^5.1.1"
},
"devDependencies": {
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@types/react-visibility-sensor": "^5.1.0",
"@vitejs/plugin-react": "^4.0.3",
"eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0",
Expand Down
5 changes: 4 additions & 1 deletion packages/mrwhale-dashboard/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ import PrivateRoute from "./shared/PrivateRoute";
import ManageGuild from "./features/dashboard/manage/ManageGuild";
import { selectIsInitialLoad } from "./features/auth/authSlice";
import Loading from "./components/Loading";
import { useGetClientInfoMutation } from "./features/client/clientApi";

function App() {
const dispatch = useDispatch();
const isInitialLoad = useSelector(selectIsInitialLoad);
const [getCurrentUser] = useGetCurrentUserMutation();
const [getClientInfo] = useGetClientInfoMutation();

// Here we are fetching the logged in user.
useEffect(() => {
getClientInfo();
getCurrentUser();
}, [dispatch, getCurrentUser]);
}, [dispatch, getClientInfo, getCurrentUser]);

if (isInitialLoad) {
return <Loading />;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/mrwhale-dashboard/src/assets/rank.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions packages/mrwhale-dashboard/src/components/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import { useAuth } from "../hooks/auth";
import { User } from "../types/user";
import { Logout, Settings } from "@mui/icons-material";
import { getInviteUrl } from "../util/get-invite-url";
import { useClient } from "../hooks/client";

function Nav(): React.JSX.Element {
const { user, isAuthenticated } = useAuth();
const { clientId } = useClient();
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(
null
);
Expand Down Expand Up @@ -110,7 +112,7 @@ function Nav(): React.JSX.Element {
>
<MenuItem
component="a"
href={getInviteUrl("414497162261430272")}
href={getInviteUrl(clientId)}
onClick={handleCloseNavMenu}
>
<Typography textAlign="center">Invite</Typography>
Expand Down Expand Up @@ -154,7 +156,7 @@ function Nav(): React.JSX.Element {
<Button
component="a"
color="inherit"
href={getInviteUrl("414497162261430272")}
href={getInviteUrl(clientId)}
sx={{ my: 1, mx: 1.5 }}
>
Invite
Expand Down
20 changes: 20 additions & 0 deletions packages/mrwhale-dashboard/src/features/client/clientApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { api } from "../../shared/api";
import { User } from "../../types/user";

interface ClientResponse {
user: User | null;
clientId: string;
userCount: number;
version: string;
}

export const clientApi = api.injectEndpoints({
endpoints: (build) => ({
getClientInfo: build.mutation<ClientResponse, void>({
query: () => `client`,
}),
}),
overrideExisting: false,
});

export const { useGetClientInfoMutation } = clientApi;
43 changes: 43 additions & 0 deletions packages/mrwhale-dashboard/src/features/client/clientSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createSlice } from "@reduxjs/toolkit";

import type { RootState } from "../../store";
import { User } from "../../types/user";
import { clientApi } from "./clientApi";

const CLIENT_FEATURE_KEY = "Client";

type ClientState = {
user: User | null;
clientId: string;
userCount: number;
version: string;
};

const slice = createSlice({
name: CLIENT_FEATURE_KEY,
initialState: {
user: null,
clientId: "",
userCount: 0,
version: "",
} as ClientState,
reducers: {},
extraReducers: (builder) => {
builder.addMatcher(
clientApi.endpoints.getClientInfo.matchFulfilled,
(state, { payload }) => {
state.user = payload.user;
state.clientId = payload.clientId;
state.userCount = payload.userCount;
state.version = payload.version;
}
);
},
});

export default slice.reducer;

export const selectClientUser = (state: RootState) => state.client.user;
export const selectClientId = (state: RootState) => state.client.clientId;
export const selectUserCount = (state: RootState) => state.client.userCount;
export const selectVersion = (state: RootState) => state.client.version;
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import { Link as RouterLink } from "react-router-dom";
import { getGuildIcon } from "../../util/get-guild-icon";
import { getInviteUrlForGuild } from "../../util/get-invite-url";
import { Guild } from "../../types/guild";
import { useClient } from "../../hooks/client";

interface Props {
guilds: Guild[];
}

const GuildList = ({ guilds }: Props) => {
const { clientId } = useClient();
return (
<Container sx={{ py: 8 }} maxWidth="md">
<Grid container spacing={4}>
Expand Down Expand Up @@ -47,7 +49,7 @@ const GuildList = ({ guilds }: Props) => {
<CardActions>
{!guild.isInvited ? (
<Button
href={getInviteUrlForGuild("414497162261430272", guild.id)}
href={getInviteUrlForGuild(clientId, guild.id)}
size="small"
>
Invite
Expand Down
4 changes: 4 additions & 0 deletions packages/mrwhale-dashboard/src/features/home/FeatureItem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.feature-image {
max-width: 100%;
border-radius: 10px;
}
83 changes: 83 additions & 0 deletions packages/mrwhale-dashboard/src/features/home/FeatureItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
Avatar,
Box,
Fade,
Grid,
List,
ListItem,
ListItemAvatar,
ListItemText,
Typography,
} from "@mui/material";
import { useState } from "react";
import VizSensor from "react-visibility-sensor";

import "./FeatureItem.css";

export interface FeatureItemProps {
title: string;
description: string;
imageSrc: string;
imageAlt: string;
list?: {
icon: JSX.Element;
primaryText: string;
secondaryText?: string;
}[];
}

const FeatureItem = ({
title,
description,
imageSrc,
imageAlt,
list,
}: FeatureItemProps) => {
const [active, setActive] = useState(false);
return (
<VizSensor
onChange={(isVisible: boolean) => {
if (isVisible) {
setActive(true);
}
}}
>
<Fade in={active} timeout={2000}>
<Box sx={{ display: "flex", mb: 20 }}>
<Grid container spacing={4}>
<Grid item xs={12} md={6} lg={6}>
<Typography variant="h3" color="text.primary" paragraph>
{title}
</Typography>
<Typography variant="body1" color="text.primary" paragraph>
{description}
</Typography>
{list && (
<List >
{list.map((item) => (
<ListItem>
<ListItemAvatar>
<Avatar>{item.icon}</Avatar>
</ListItemAvatar>
<ListItemText
primary={item.primaryText}
secondary={
item.secondaryText ? item.secondaryText : null
}
/>
</ListItem>
))}
</List>
)}
</Grid>
<Grid item xs={12} md={6} lg={6}>
<img src={imageSrc} alt={imageAlt} className="feature-image" />
</Grid>
</Grid>
</Box>
</Fade>
</VizSensor>
);
};

export default FeatureItem;
90 changes: 78 additions & 12 deletions packages/mrwhale-dashboard/src/features/home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
import { Box, Button, Container, Stack, Typography } from "@mui/material";
import EmojiEventsIcon from "@mui/icons-material/EmojiEvents";
import { Link as RouterLink } from "react-router-dom";

import "./Home.css";
import { getInviteUrl } from "../../util/get-invite-url";
import { useAuth } from "../../hooks/auth";
import FeatureItem, { FeatureItemProps } from "./FeatureItem";
import { useClient } from "../../hooks/client";

const features: FeatureItemProps[] = [
{
title: "🏆 Level up",
description:
"Compete with friends in your server by gaining EXP and levelling up in the leaderboards.",
imageSrc: "/src/assets/level-advance.png",
imageAlt: "Level up",
},
{
title: "💯 Rank Cards",
description:
"Discover how you rank up with your very own ranking card. This shows your current progress and includes your rank, level and EXP.",
imageSrc: "/src/assets/rank.png",
imageAlt: "Rank card",
},
{
title: "📈 Leaderboards",
description: "Mr. Whale supports both global and server leaderboards.",
imageSrc: "/src/assets/leaderboard.png",
imageAlt: "Leaderboard",
list: [
{
icon: <EmojiEventsIcon color="secondary" />,
primaryText: "Global Leaderboard",
secondaryText:
" This is the top 10 players across discord. Every discord server you use Mr. Whale in counts towards this.",
},
{
icon: <EmojiEventsIcon color="secondary" />,
primaryText: "Server Leaderboards",
secondaryText: "This is the top 10 players in the server.",
},
],
},
];

const Home = () => {
const { user, isAuthenticated } = useAuth();
const { clientId, userCount } = useClient();

return (
<>
<div className="wave">
Expand Down Expand Up @@ -43,14 +86,24 @@ const Home = () => {
>
<Button
component="a"
href={getInviteUrl("414497162261430272")}
href={getInviteUrl(clientId)}
variant="contained"
>
Add to Discord
</Button>
<Button variant="outlined" component={RouterLink} to="/dashboard">
Dashboard
</Button>
{isAuthenticated && user ? (
<Button
variant="outlined"
component={RouterLink}
to="/dashboard"
>
Dashboard
</Button>
) : (
<Button variant="outlined" href="/authorize/login">
Login
</Button>
)}
</Stack>
</Container>
<Container sx={{ pt: 4 }}>
Expand All @@ -65,16 +118,29 @@ const Home = () => {
</svg>
</div>

{features.map((feature) => (
<FeatureItem
title={feature.title}
description={feature.description}
imageSrc={feature.imageSrc}
imageAlt={feature.imageAlt}
list={feature.list}
/>
))}

<Typography variant="h5" align="center" color="text.secondary" paragraph>
So what are you waiting for? Join {userCount} Discord users and invite
Mr. Whale to your server today.
</Typography>
<Box
sx={{
pt: 8,
pb: 6,
}}
sx={{ pt: 4 }}
display="flex"
justifyContent="center"
alignItems="center"
>
<Typography variant="h3" color="text.secondary" paragraph>
🏆Levelling
</Typography>
<Typography>Compete with friends in your server.</Typography>
<Button component="a" href={getInviteUrl(clientId)} variant="contained">
Add to Discord
</Button>
</Box>
</>
);
Expand Down
23 changes: 23 additions & 0 deletions packages/mrwhale-dashboard/src/hooks/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useMemo } from "react";
import { useSelector } from "react-redux";

import {
selectClientUser,
selectClientId,
selectUserCount,
selectVersion,
} from "../features/client/clientSlice";

export const useClient = () => {
const user = useSelector(selectClientUser);
const clientId = useSelector(selectClientId);
const userCount = useSelector(selectUserCount);
const version = useSelector(selectVersion);

return useMemo(() => ({ user, clientId, userCount, version }), [
user,
clientId,
userCount,
version,
]);
};
Loading

0 comments on commit 544e26b

Please sign in to comment.