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 ( -
-
- logo -

Hello Vite + React!

-

- -

-

- Edit App.tsx and save to test HMR updates! -

-

- - Learn React - - {' | '} - - Vite Docs - -

-
+
+
+
+
+ Placeholder image +
+
+
+
+
+
+ Placeholder image +
+
+
+

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"