diff --git a/backend/db/user.go b/backend/db/user.go
index f2e0d5d..e8381c4 100644
--- a/backend/db/user.go
+++ b/backend/db/user.go
@@ -22,7 +22,8 @@ type User struct {
AvatarURL *string
Links []string
- Discord *string
+ Discord *string
+ DiscordUsername *string
}
// usernames must match this regex
diff --git a/backend/routes/user/get_user.go b/backend/routes/user/get_user.go
index f5217ee..644a8aa 100644
--- a/backend/routes/user/get_user.go
+++ b/backend/routes/user/get_user.go
@@ -20,6 +20,19 @@ type GetUserResponse struct {
Links []string `json:"links"`
}
+type GetMeResponse struct {
+ ID xid.ID `json:"id"`
+ Username string `json:"username"`
+ DisplayName *string `json:"display_name"`
+ Bio *string `json:"bio"`
+ AvatarSource *string `json:"avatar_source"`
+ AvatarURL *string `json:"avatar_url"`
+ Links []string `json:"links"`
+
+ Discord *string `json:"discord"`
+ DiscordUsername *string `json:"discord_username"`
+}
+
type PartialMember struct {
ID xid.ID `json:"id"`
Name string `json:"name"`
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index c12d66f..660cdd1 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,45 +1,44 @@
-import { useState } from 'react'
-import logo from './logo.svg'
-import './App.css'
+import "./App.css";
function App() {
- const [count, setCount] = useState(0)
-
return (
-
-
-
- Hello Vite + React!
-
-
-
-
- Edit App.tsx
and save to test HMR updates!
-
-
-
- Learn React
-
- {' | '}
-
- Vite Docs
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
John Smith
+
@johnsmith
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
+ nec iaculis mauris.
@bulmaio.
#css{" "}
+
#responsive
+
+
+
+
+
- )
+ );
}
-export default App
+export default App;
diff --git a/frontend/src/index.css b/frontend/src/index.css
index ec2585e..e69de29 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
-}
diff --git a/frontend/src/lib/store.ts b/frontend/src/lib/store.ts
new file mode 100644
index 0000000..8a64a01
--- /dev/null
+++ b/frontend/src/lib/store.ts
@@ -0,0 +1,23 @@
+import axios from "axios";
+import { atom } from "recoil";
+import type { APIError, MeUser } from "./types";
+
+export const userState = atom
({
+ key: "userState",
+ default: getCurrentUser(),
+});
+
+async function getCurrentUser(): Promise {
+ const token = localStorage.getItem("pronouns-token");
+ if (!token) return null;
+
+ try {
+ const resp = await axios.get("/api/v1/users/@me");
+ if ("id" in resp.data) return resp.data as MeUser;
+ return null;
+ } catch (e) {
+ console.log("Error fetching /users/@me:", e);
+ }
+
+ return null;
+}
diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts
new file mode 100644
index 0000000..fffff74
--- /dev/null
+++ b/frontend/src/lib/types.ts
@@ -0,0 +1,27 @@
+export interface MeUser {
+ id: string;
+ username: string;
+ display_name: string | null;
+ bio: string | null;
+ avatar_source: string | null;
+ avatar_url: string | null;
+ links: string[] | null;
+ discord: string | null;
+ discord_username: string | null;
+}
+
+export interface APIError {
+ code: ErrorCode;
+ message?: string;
+}
+
+export enum ErrorCode {
+ BadRequest = 400,
+ Forbidden = 403,
+ InternalServerError = 500,
+
+ InvalidState = 1001,
+ InvalidOAuthCode = 1002,
+
+ UserNotFound = 2001,
+}
diff --git a/frontend/src/logo.svg b/frontend/src/logo.svg
deleted file mode 100644
index 6b60c10..0000000
--- a/frontend/src/logo.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 4a1b150..8b91d81 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,10 +1,18 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
-import App from './App'
-import './index.css'
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { BrowserRouter } from "react-router-dom";
+import { RecoilRoot } from "recoil";
-ReactDOM.createRoot(document.getElementById('root')!).render(
+import App from "./App";
+import "../../node_modules/bulma/css/bulma.css";
+import "./index.css";
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
-
+
+
+
+
+
-)
+);
diff --git a/package.json b/package.json
index b3b87b0..abf766a 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,12 @@
"preview": "vite preview"
},
"dependencies": {
+ "axios": "^0.27.2",
+ "bulma": "^0.9.3",
"react": "^18.0.0",
- "react-dom": "^18.0.0"
+ "react-dom": "^18.0.0",
+ "react-router-dom": "6",
+ "recoil": "^0.7.2"
},
"devDependencies": {
"@types/react": "^18.0.0",
diff --git a/yarn.lock b/yarn.lock
index 31d24f9..be52861 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -203,6 +203,13 @@
"@babel/plugin-syntax-jsx" "^7.16.7"
"@babel/types" "^7.17.0"
+"@babel/runtime@^7.7.6":
+ version "7.17.9"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
+ integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/template@^7.16.7":
version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
@@ -322,6 +329,19 @@ ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+axios@^0.27.2:
+ version "0.27.2"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
+ integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
+ dependencies:
+ follow-redirects "^1.14.9"
+ form-data "^4.0.0"
+
browserslist@^4.20.2:
version "4.20.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf"
@@ -333,6 +353,11 @@ browserslist@^4.20.2:
node-releases "^2.0.3"
picocolors "^1.0.0"
+bulma@^0.9.3:
+ version "0.9.3"
+ resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.9.3.tgz#ddccb7436ebe3e21bf47afe01d3c43a296b70243"
+ integrity sha512-0d7GNW1PY4ud8TWxdNcP6Cc8Bu7MxcntD/RRLGWuiw/s0a9P+XlH/6QoOIrmbj6o8WWJzJYhytiu9nFjTszk1g==
+
caniuse-lite@^1.0.30001332:
version "1.0.30001335"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz#899254a0b70579e5a957c32dced79f0727c61f2a"
@@ -359,6 +384,13 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
convert-source-map@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
@@ -378,6 +410,11 @@ debug@^4.1.0:
dependencies:
ms "2.1.2"
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
electron-to-chromium@^1.4.118:
version "1.4.132"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.132.tgz#b64599eb018221e52e2e4129de103b03a413c55d"
@@ -524,6 +561,20 @@ estree-walker@^2.0.1:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
+follow-redirects@^1.14.9:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4"
+ integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
@@ -544,6 +595,11 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+hamt_plus@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz#e21c252968c7e33b20f6a1b094cd85787a265601"
+ integrity sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE=
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -556,6 +612,13 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
+history@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
+ integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==
+ dependencies:
+ "@babel/runtime" "^7.7.6"
+
is-core-module@^2.8.1:
version "2.9.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69"
@@ -585,6 +648,18 @@ loose-envify@^1.1.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@@ -637,6 +712,21 @@ react-refresh@^0.13.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.13.0.tgz#cbd01a4482a177a5da8d44c9755ebb1f26d5a1c1"
integrity sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==
+react-router-dom@6:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d"
+ integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==
+ dependencies:
+ history "^5.2.0"
+ react-router "6.3.0"
+
+react-router@6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557"
+ integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==
+ dependencies:
+ history "^5.2.0"
+
react@^18.0.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
@@ -644,6 +734,18 @@ react@^18.0.0:
dependencies:
loose-envify "^1.1.0"
+recoil@^0.7.2:
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/recoil/-/recoil-0.7.2.tgz#37aafc9e0674abae639263354a11c910e71bf78a"
+ integrity sha512-OT4pI7FOUHcIoRtjsL5Lqq+lFFzQfir4MIbUkqyJ3nqv3WfBP1pHepyurqTsK5gw+T+I2R8+uOD28yH+Lg5o4g==
+ dependencies:
+ hamt_plus "1.0.2"
+
+regenerator-runtime@^0.13.4:
+ version "0.13.9"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
+ integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
+
resolve@^1.22.0:
version "1.22.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"