diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3662b370 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/backend/models/user.ts b/backend/models/user.ts index 290171ac..1066911e 100644 --- a/backend/models/user.ts +++ b/backend/models/user.ts @@ -3,11 +3,13 @@ import { ObjectId } from "mongodb" type User = { id: ObjectId; name: string; + bio?: string; email: string; password: string; avatar: string; createdAt?: Date; location?: string; + isAdmin?: boolean; } export default User \ No newline at end of file diff --git a/backend/utils/secrets.ts b/backend/utils/secrets.ts index b0a1c7a7..d8a1034e 100644 --- a/backend/utils/secrets.ts +++ b/backend/utils/secrets.ts @@ -6,6 +6,7 @@ if (!fs.existsSync('.env')) { } export const ENVIRONMENT = process.env.NODE_ENV -export const IS_PROD = ENVIRONMENT === 'production' +// export const IS_PROD = ENVIRONMENT === 'production' +export const IS_PROD = true export const MONGO_URI = IS_PROD ? process.env.MONGO_URI : process.env.MONGO_URI_LOCAL diff --git a/components/Admin/Analytics/Analytics.Styled.tsx b/components/Admin/Analytics/Analytics.Styled.tsx new file mode 100644 index 00000000..1a041f11 --- /dev/null +++ b/components/Admin/Analytics/Analytics.Styled.tsx @@ -0,0 +1,36 @@ +import styled from 'styled-components' + +export const StyledAnalytics = styled.div` + .analytics-group { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + grid-gap: 20px; + + .analytics-group-item { + border-radius: 6px; + width: 100%; + background-color: rgb(255, 255, 255, 0.075); + + .analytics-heading { + padding: 12px 20px; + border-bottom: 1px solid rgb(255, 255, 255, 0.075); + + .analytics-heading-title { + font-size: 13px; + font-weight: 600; + letter-spacing: 0.05rem; + color: rgb(255, 255, 255, 0.45); + } + } + + .analytics-data { + padding: 20px; + + .analytics-amount { + font-size: 32px; + font-weight: 400; + } + } + } + } +` \ No newline at end of file diff --git a/components/Auth/Login.tsx b/components/Auth/Login.tsx index 686472e8..bdcbe589 100644 --- a/components/Auth/Login.tsx +++ b/components/Auth/Login.tsx @@ -56,8 +56,10 @@ const Login: FC = () => { updateUser({ id: resData._id, name: resData.name, + bio: resData.bio, email: resData.email, avatar: resData.avatar, + isAdmin: resData.isAdmin }) ) diff --git a/components/Auth/Register.tsx b/components/Auth/Register.tsx index 09f80356..2e7fbc11 100644 --- a/components/Auth/Register.tsx +++ b/components/Auth/Register.tsx @@ -79,9 +79,11 @@ const Register: FC = () => { if (res.success) { dispatch(updateUser({ id: resData._id, - name: resData.name, + name: resData.name, + bio: resData.bio, email: resData.email, - avatar: resData.avatar + avatar: resData.avatar, + isAdmin: resData.isAdmin })) router.push('/') diff --git a/components/Layout/Sidebar/Sidebar/Sidebar.tsx b/components/Layout/Sidebar/Sidebar/Sidebar.tsx index 4acd5de4..156c8a71 100644 --- a/components/Layout/Sidebar/Sidebar/Sidebar.tsx +++ b/components/Layout/Sidebar/Sidebar/Sidebar.tsx @@ -1,10 +1,14 @@ import { HomeIcon, MapIcon, UsersIcon, HeartIcon, DesktopComputerIcon } from '@heroicons/react/outline' import Link from 'next/link' import React, { FC } from 'react' +import { useSelector } from 'react-redux' import { StyledSidebar } from '.' +import { selectUser } from '../../../../redux/user' import { Item } from './Item' const Sidebar: FC = () => { + const user = useSelector(selectUser) + return (
@@ -73,7 +77,7 @@ const Sidebar: FC = () => {
-
+ {/*
Learn
@@ -99,7 +103,23 @@ const Sidebar: FC = () => { Languages
- + */} + + {user.isAdmin && ( +
+
+ Admin +
+ +
+ + + Analytics + + +
+
+ )}
) } diff --git a/components/System/Avatar/Avatar.Styled.tsx b/components/System/Avatar/Avatar.Styled.tsx index fafb7526..b7b5c120 100644 --- a/components/System/Avatar/Avatar.Styled.tsx +++ b/components/System/Avatar/Avatar.Styled.tsx @@ -11,6 +11,9 @@ const StyledAvatar = styled.div` height: ${({ size }) => size ? size : '32'}px; width: ${({ size }) => size ? size : '32'}px; cursor: pointer; + background-color: #131315; + border-radius: 50%; + position: relative; @media (max-width: 600px) { height: ${({ mobileSize }) => mobileSize && mobileSize}px; @@ -18,7 +21,7 @@ const StyledAvatar = styled.div` } img { - border: ${({ outline, customOutline }) => outline ? '1px solid rgba(255, 255, 255, 0.10)' : + box-shadow: ${({ outline, customOutline }) => outline ? 'inset 0 0 0 1px rgba(255, 255, 255, 0.10)' : (customOutline ? customOutline : 'none')}!important; border-radius: 50%!important; } diff --git a/pages/admin/analytics/index.tsx b/pages/admin/analytics/index.tsx new file mode 100644 index 00000000..a0c60656 --- /dev/null +++ b/pages/admin/analytics/index.tsx @@ -0,0 +1,88 @@ +import type { NextPage } from 'next' +import styled from 'styled-components' +import React, { useEffect, useState } from 'react' +import { Layout } from '../../../components/Layout' +import { StyledAnalytics } from '../../../components/Admin/Analytics/Analytics.Styled' +import { mailman } from '../../../backend/utils/mailman' + +const StyledHeader = styled.h1` + font-size: 1.75rem; + font-weight: 700; + color: #fff; +` + +type AnalyticsType = { + users: number, + spGames: number, + challenges: number, + aerialGames: number, +} + +const AnalyticsPage: NextPage = () => { + const [loading, setLoading] = useState(true) + const [analytics, setAnalytics] = useState() + + const loadAnalytics = async () => { + setLoading(true) + + const { status, res: { data } } = await mailman('analytics', 'GET') + + setAnalytics(data) + + setLoading(false) + } + + useEffect(() => { + loadAnalytics() + }, []) + + return ( + + Analytics + + + {loading && ( + Loading... + )} + {!loading && ( +
+
+
+ USERS +
+
+ {analytics?.users} +
+
+
+
+ SINGLE PLAYER GAMES +
+
+ {analytics?.spGames} +
+
+
+
+ CHALLENGES +
+
+ {analytics?.challenges} +
+
+
+
+ AERIAL GAMES +
+
+ {analytics?.aerialGames} +
+
+
+ )} +
+
+ ) +} + +export default AnalyticsPage diff --git a/pages/api/analytics/index.ts b/pages/api/analytics/index.ts new file mode 100644 index 00000000..5f931e34 --- /dev/null +++ b/pages/api/analytics/index.ts @@ -0,0 +1,34 @@ +import { collections, dbConnect } from '../../../backend/utils/dbConnect' +import { NextApiRequest, NextApiResponse } from 'next' + +export default async (req: NextApiRequest, res: NextApiResponse) => { + try { + await dbConnect() + + if (req.method === 'GET') { + const userCount = await collections.users?.estimatedDocumentCount() + const spGamesCount = await collections.games?.estimatedDocumentCount() + const challengesCount = await collections.challenges?.estimatedDocumentCount() + const aerialCount = await collections.aerialGames?.estimatedDocumentCount() + + + + res.status(200).json({ + success: true, + data: { + users: userCount, + spGames: spGamesCount, + challenges: challengesCount, + aerialGames: aerialCount, + recentUsers: recentUsers + } + }) + } + else { + res.status(500).json({ message: 'Invalid request' }) + } + } + catch (err) { + res.status(500).json({ message: 'Something went wrong, please try again later' }) + } +} \ No newline at end of file diff --git a/pages/api/users/count.ts b/pages/api/users/count.ts new file mode 100644 index 00000000..2e805996 --- /dev/null +++ b/pages/api/users/count.ts @@ -0,0 +1,25 @@ +import { collections, dbConnect } from '../../../backend/utils/dbConnect' +import { NextApiRequest, NextApiResponse } from 'next' + +export default async (req: NextApiRequest, res: NextApiResponse) => { + try { + await dbConnect() + + if (req.method === 'GET') { + const count = await collections.users?.estimatedDocumentCount() + + res.status(200).json({ + success: true, + data: { + count + } + }) + } + else { + res.status(500).json({ message: 'Invalid request' }) + } + } + catch (err) { + res.status(500).json({ message: 'Something went wrong, please try again later' }) + } +} \ No newline at end of file diff --git a/pages/user/[id].tsx b/pages/user/[id].tsx index 8d6620dd..d58c7914 100644 --- a/pages/user/[id].tsx +++ b/pages/user/[id].tsx @@ -1,17 +1,17 @@ +import { PencilAltIcon } from '@heroicons/react/solid' import type { NextPage } from 'next' import { useRouter } from 'next/router' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { mailman } from '../../backend/utils/mailman' import { Layout, LoadingPage } from '../../components/Layout' -import { Avatar, Button, FlexGroup } from '../../components/System' -import { logOutUser } from '../../redux/user' -import { selectUser } from '../../redux/user' +import { logOutUser, selectUser, updateBio, updateUsername } from '../../redux/user' import StyledProfilePage from '../../styles/ProfilePage.Styled' const ProfilePage: NextPage = () => { const banner = '/images/backgrounds/prettyImage2.jpeg' - const userBio = 'Hey there, I am the best explorer on this application!' + const [newProfileValues, setNewProfileValues] = useState<{ name: string, bio?: string }>() + const [isEditing, setIsEditing] = useState(false) const [userDetails, setUserDetails] = useState() const [loading, setLoading] = useState(true) const user = useSelector(selectUser) @@ -38,17 +38,35 @@ const ProfilePage: NextPage = () => { dispatch(logOutUser()) } + + const updateUserInfo = () => { + dispatch(updateBio(newProfileValues?.bio)) + dispatch(updateUsername(newProfileValues?.name)) + setUserDetails({ + ...userDetails, + name: newProfileValues?.name, + bio: newProfileValues?.bio + }) + setIsEditing(false) + } + + const cancelEditing = () => { + setNewProfileValues({ name: userDetails.name, bio: userDetails.bio }) + setIsEditing(false) + } useEffect(() => { // if this users profile use the cached data in redux store if (isThisUsersProfile()) { - setUserDetails({name: user.name, avatar: user.avatar}) + setUserDetails({name: user.name, bio: user.bio, avatar: user.avatar}) + setNewProfileValues({name: user.name, bio: user.bio}) setLoading(false) } else { const fetchUserDetails = async () => { const { res } = await mailman(`users/${userId}`) setUserDetails(res) + setNewProfileValues({name: res.name, bio: res.bio}) setLoading(false) } @@ -62,100 +80,129 @@ const ProfilePage: NextPage = () => { return ( - -
-
- User Banner -
- -
-
- -
- - - {isThisUsersProfile() && ( - <> - - - + +
+
+
+
+
+ {userDetails.name}/ +
+

{isEditing ? setNewProfileValues({name: e.target.value, bio: newProfileValues?.bio})}/> : userDetails.name}

+ {userDetails.bio && {isEditing ? : userDetails.bio}} + {isThisUsersProfile() && !isEditing && ( +
+ + +
)} - - {!isThisUsersProfile() && ( - - )} - -
- -
-

{userDetails.name}

- {userBio} -
- -
-

Statistics

- -
-
-
-

{stats.completedGames}

- Games Played -
+ {isEditing && ( +
+ + +
+ )} +
+
+ + + {/*
+
+ User Banner +
+ +
+
+ +
+ + + {isThisUsersProfile() && ( + <> + + + + )} + + {!isThisUsersProfile() && ( + + )} + +
+ +
+

{userDetails.name}

+ {userDetails.bio || 'Hey there, I am the best explorer on this application!'} +
+ +
+

Statistics

+ +
+
+
+

{stats.completedGames}

+ Games Played
+
-
-
-

{stats.bestGame}

- Best Score -
+
+
+

{stats.bestGame}

+ Best Score
+
-
-
-

{stats.avgScore}

- Avg. Score -
+
+
+

{stats.avgScore}

+ Avg. Score
-
-
+ + +
-
-

Badges

+
+

Badges

-
-
- - First Game -
+
+
+ + First Game +
-
- - First Country -
+
+ + First Country +
-
- - Perfect Score -
+
+ + Perfect Score +
-
- - Perfect Game -
- -
- - Challenge Win -
- -
- - Perfect Game -
+
+ + Perfect Game
-
-
- + +
+ + Challenge Win +
+ +
+ + Perfect Game +
+ +
+
*/}
) } diff --git a/public/images/avatars/banana.jpg b/public/images/avatars/banana.jpg new file mode 100644 index 00000000..ec6343cb Binary files /dev/null and b/public/images/avatars/banana.jpg differ diff --git a/redux/user.tsx b/redux/user.tsx index 62f94262..a9f521e4 100644 --- a/redux/user.tsx +++ b/redux/user.tsx @@ -1,11 +1,12 @@ import { createSlice } from '@reduxjs/toolkit' -import { LocationType } from '../types' type UserState = { id: string; name: string; + bio?: string; email: string; avatar: string; + isAdmin?: boolean; guessMapSize: number; location: {lat: number, lng: number} | null; } @@ -26,6 +27,8 @@ export const userSlice = createSlice({ updateUser: (state, action) => { state.id = action.payload.id state.name = action.payload.name + state.bio = action.payload.bio + state.isAdmin = action.payload.isAdmin state.email = action.payload.email || '' state.avatar = action.payload.avatar || '' }, @@ -33,7 +36,10 @@ export const userSlice = createSlice({ state.avatar = action.payload.avatar }, updateUsername: (state, action) => { - state.name = action.payload.name + state.name = action.payload + }, + updateBio: (state, action) => { + state.bio = action.payload }, updateEmail: (state, action) => { state.email = action.payload.email @@ -53,7 +59,8 @@ export const userSlice = createSlice({ export const { updateUser, updateAvatar, - updateUsername, + updateUsername, + updateBio, updateEmail, updateGuessMapSize, updateLocation, diff --git a/styles/ProfilePage.Styled.tsx b/styles/ProfilePage.Styled.tsx index d637231f..73462818 100644 --- a/styles/ProfilePage.Styled.tsx +++ b/styles/ProfilePage.Styled.tsx @@ -1,203 +1,377 @@ import styled from 'styled-components' const StyledProfilePage = styled.div` - .profileWrapper { - border: 1px solid #141414; - border-radius: 12px; - background: #0f0f0f; - - @media (max-width: 600px) { - border-radius: 0; - } - } - - // Override Horizontal Padding In Layout.Styled - .mainContent { - @media (max-width: 600px) { - padding: 0; - } - } - - .userBanner { - position: relative; - height: 200px; + .banner { width: 100%; - opacity: 0.75; - border-bottom: var(--border); - - @media (max-width: 600px) { - height: 120px; - } + height: 200px; + background-color: rgb(255, 255, 255, 0.02); + border-radius: 10px; + position: relative; - img { + &::after { + content: ''; position: absolute; + z-index: 1; + border-radius: 10px; + width: 100%; + height: 100%; top: 0; left: 0; right: 0; bottom: 0; - object-fit: cover; - height: 100%; - width: 100%; - border-radius: 12px 12px 0 0; - - @media (max-width: 600px) { - border-radius: 0; - } + box-shadow: inset 0 0 0 1px rgb(255, 255, 255, 0.1); } } - .profileTop { - display: flex; - align-items: flex-end; - justify-content: space-between; - margin-top: -3.8rem; - padding: 0 2.5rem 2rem 2.5rem; - - @media (max-width: 1050px) { - padding: 0 1rem 2rem 1rem; - } - } - - .userDetails { - border-bottom: 1px solid #202020; - padding: 0 2.5rem 2rem 2.5rem; - - @media (max-width: 1050px) { - padding: 0 1rem 2rem 1rem; - } - } - - .userName { - margin-bottom: 0.8rem; - font-weight: 700; - font-size: 1.75rem; - - @media (max-width: 600px) { - font-size: 1.5rem; - } - } - - .userBio { - color: #808080; - font-size: 1rem; - } - - .userStats { - padding: 3rem 2.5rem 0 2.5rem; - - @media (max-width: 1050px) { - padding: 3rem 1rem 0 1rem; - } - } - - .statRow { - display: flex; - align-items: center; - gap: 1rem; - padding-top: 1.5rem; - - @media (max-width: 500px) { - gap: 0.5rem; - } - } - - .statItem { - background-color: transparent; - border: 1px solid rgba(255, 255, 255, 0.05); - border-radius: 12px; - display: flex; - align-items: center; - justify-content: center; + .profile-details { + max-width: 600px; + margin: 0 auto; width: 100%; - padding: 1.2rem; - box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); - - @media (max-width: 700px) { - padding: 0.75rem; - } - - @media (max-width: 500px) { - padding: 0.5rem; - } - } - - .statContent { - display: flex; - align-items: center; - flex-direction: column; - gap: 0.3rem; - } - - .statResult { - font-weight: 600; - - @media (max-width: 1000px) { - font-size: 1.25rem; - } - } - - .statLabel { - color: var(--lightPurple); + position: relative; + z-index: 2; + margin-top: -60px; + padding-bottom: 30px; + border-bottom: 1px solid rgb(255, 255, 255, 0.1); + + .profile-avatar { + background-color: #0e0e10; + width: 125px; + height: 125px; + border-radius: 50%; + position: relative; + box-shadow: 0 0 0 5px #0e0e10; + + img { + position: absolute; + object-fit: cover; + border-radius: 50%; + width: 100%; + height: 100%; + top: 0; + left: 0; + right: 0; + bottom: 0; + } - @media (max-width: 1000px) { - font-size: 14px; + &::after { + content: ''; + position: absolute; + z-index: 1; + border-radius: 50%; + width: 100%; + height: 100%; + top: 0; + left: 0; + right: 0; + bottom: 0; + box-shadow: inset 0 0 0 1px rgb(255, 255, 255, 0.1); + } } - @media (max-width: 650px) { - font-size: 13px; + .profile-name { + margin-top: 20px; + font-size: 28px; + font-weight: 600; + + input { + font-size: 28px; + font-weight: 600; + color: white; + border-radius: 2px; + width: 100%; + background: rgb(255, 255, 255, 0.05); + box-shadow: 0 0 0 2px rgb(255, 255, 255, 0.05); + } } - } - - .userBadges { - padding: 4rem 2.5rem 1.5rem 2.5rem; - @media (max-width: 1050px) { - padding: 4rem 1rem 1.5rem 1rem; + .profile-bio { + display: block; + margin-top: 6px; + color: rgb(255, 255, 255, 0.5); + + textarea { + color: rgb(255, 255, 255, 0.5); + font-weight: 500; + width: 100%; + border-radius: 2px; + background: rgb(255, 255, 255, 0.05); + box-shadow: 0 0 0 2px rgb(255, 255, 255, 0.05); + resize: vertical; + } } - } - - .badgesRow { - display: grid; - grid-template-columns: repeat(6, 1fr); - padding-top: 1.5rem; - gap: 2rem; - @media (max-width: 1000px) { - grid-template-columns: repeat(3, 1fr); + .profile-actions { + margin-top: 30px; + display: flex; + + button { + padding: 1px 14px 0 14px; + font-weight: 500; + user-select: none; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + border: none; + transition: 0.2s; + border-radius: 6px; + min-width: 75px; + background-color: rgb(255, 255, 255, 0.1); + color: rgb(255, 255, 255, 0.7); + + span { + position: relative; + top: 1px; + } + + svg { + height: 20px; + position: relative; + top: -1px; + margin-right: 8px; + } + + &:hover { + cursor: pointer; + background-color: rgb(255, 255, 255, 0.15); + } + + &:not(:last-child) { + margin-right: 10px; + } + + &.logout-btn { + color: #fee2e2; + background-color: #7f1d1d; + + &:hover { + background-color: #991b1b; + } + } + } } } - .badgeItem { - display: flex; + .edit-btn { + display: inline-flex; align-items: center; - flex-direction: column; - gap: 0.5rem; - } - - .badgeLabel { - font-size: 15px; - - @media (max-width: 630px) { - font-size: 13px; + justify-content: center; + width: 20px; + height: 20px; + border-radius: 3px; + vertical-align: bottom; + margin-left: 4px; + background-color: rgb(255, 255, 255, 0.1); + color: rgb(255, 255, 255, 0.8); + transition: 0.2s; + + svg { + height: 16px; } - } - - .sectionTitle { - font-size: 1.5rem; - font-weight: 600; - color: var(--color2); - @media (max-width: 600px) { - font-size: 1.25rem; + &:hover { + background-color: rgb(255, 255, 255, 0.15); + color: rgb(255, 255, 255, 0.9); } } - .badgeImg { - @media (max-width: 500px) { - height: 60px; - width: 60px; - } - } + // .profileWrapper { + // border: 1px solid #141414; + // border-radius: 12px; + // background: #0f0f0f; + + // @media (max-width: 600px) { + // border-radius: 0; + // } + // } + + // // Override Horizontal Padding In Layout.Styled + // .mainContent { + // @media (max-width: 600px) { + // padding: 0; + // } + // } + + // .userBanner { + // position: relative; + // height: 200px; + // width: 100%; + // opacity: 0.75; + // border-bottom: var(--border); + + // @media (max-width: 600px) { + // height: 120px; + // } + + // img { + // position: absolute; + // top: 0; + // left: 0; + // right: 0; + // bottom: 0; + // object-fit: cover; + // height: 100%; + // width: 100%; + // border-radius: 12px 12px 0 0; + + // @media (max-width: 600px) { + // border-radius: 0; + // } + // } + // } + + // .profileTop { + // display: flex; + // align-items: flex-end; + // justify-content: space-between; + // margin-top: -3.8rem; + // padding: 0 2.5rem 2rem 2.5rem; + + // @media (max-width: 1050px) { + // padding: 0 1rem 2rem 1rem; + // } + // } + + // .userDetails { + // border-bottom: 1px solid #202020; + // padding: 0 2.5rem 2rem 2.5rem; + + // @media (max-width: 1050px) { + // padding: 0 1rem 2rem 1rem; + // } + // } + + // .userName { + // margin-bottom: 0.8rem; + // font-weight: 700; + // font-size: 1.75rem; + + // @media (max-width: 600px) { + // font-size: 1.5rem; + // } + // } + + // .userBio { + // color: #808080; + // font-size: 1rem; + // } + + // .userStats { + // padding: 3rem 2.5rem 0 2.5rem; + + // @media (max-width: 1050px) { + // padding: 3rem 1rem 0 1rem; + // } + // } + + // .statRow { + // display: flex; + // align-items: center; + // gap: 1rem; + // padding-top: 1.5rem; + + // @media (max-width: 500px) { + // gap: 0.5rem; + // } + // } + + // .statItem { + // background-color: transparent; + // border: 1px solid rgba(255, 255, 255, 0.05); + // border-radius: 12px; + // display: flex; + // align-items: center; + // justify-content: center; + // width: 100%; + // padding: 1.2rem; + // box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); + + // @media (max-width: 700px) { + // padding: 0.75rem; + // } + + // @media (max-width: 500px) { + // padding: 0.5rem; + // } + // } + + // .statContent { + // display: flex; + // align-items: center; + // flex-direction: column; + // gap: 0.3rem; + // } + + // .statResult { + // font-weight: 600; + + // @media (max-width: 1000px) { + // font-size: 1.25rem; + // } + // } + + // .statLabel { + // color: var(--lightPurple); + + // @media (max-width: 1000px) { + // font-size: 14px; + // } + + // @media (max-width: 650px) { + // font-size: 13px; + // } + // } + + // .userBadges { + // padding: 4rem 2.5rem 1.5rem 2.5rem; + + // @media (max-width: 1050px) { + // padding: 4rem 1rem 1.5rem 1rem; + // } + // } + + // .badgesRow { + // display: grid; + // grid-template-columns: repeat(6, 1fr); + // padding-top: 1.5rem; + // gap: 2rem; + + // @media (max-width: 1000px) { + // grid-template-columns: repeat(3, 1fr); + // } + // } + + // .badgeItem { + // display: flex; + // align-items: center; + // flex-direction: column; + // gap: 0.5rem; + // } + + // .badgeLabel { + // font-size: 15px; + + // @media (max-width: 630px) { + // font-size: 13px; + // } + // } + + // .sectionTitle { + // font-size: 1.5rem; + // font-weight: 600; + // color: var(--color2); + + // @media (max-width: 600px) { + // font-size: 1.25rem; + // } + // } + + // .badgeImg { + // @media (max-width: 500px) { + // height: 60px; + // width: 60px; + // } + // } ` export default StyledProfilePage diff --git a/styles/globals.css b/styles/globals.css index e442b969..9624fbb7 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -3,55 +3,55 @@ @font-face { font-family: 'Graphik'; font-weight: 100; - src: local('Graphik'), url(../fonts/Graphik/Graphik-100-Thin.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-100-Thin.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 200; - src: local('Graphik'), url(../fonts/Graphik/Graphik-200-Extralight.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-200-Extralight.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 300; - src: local('Graphik'), url(../fonts/Graphik/Graphik-300-Light.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-300-Light.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 400; - src: local('Graphik'), url(../fonts/Graphik/Graphik-400-Regular.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-400-Regular.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 500; - src: local('Graphik'), url(../fonts/Graphik/Graphik-500-Medium.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-500-Medium.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 600; - src: local('Graphik'), url(../fonts/Graphik/Graphik-600-Semibold.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-600-Semibold.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 700; - src: local('Graphik'), url(../fonts/Graphik/Graphik-700-Bold.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-700-Bold.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 800; - src: local('Graphik'), url(../fonts/Graphik/Graphik-800-Black.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-800-Black.otf) format('opentype'); } @font-face { font-family: 'Graphik'; font-weight: 900; - src: local('Graphik'), url(../fonts/Graphik/Graphik-900-Super.otf) format('opentype'); + src: url(../fonts/Graphik/Graphik-900-Super.otf) format('opentype'); } :root { diff --git a/types/User.tsx b/types/User.tsx index 376397fb..4f1fe074 100644 --- a/types/User.tsx +++ b/types/User.tsx @@ -1,10 +1,12 @@ type User = { id: string name: string + bio?: string email: string avatar: string createdAt?: Date location?: string + isAdmin?: boolean } export default User \ No newline at end of file