-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'next' of https://github.com/HolodexNet/Holodex into next
- Loading branch information
Showing
17 changed files
with
1,382 additions
and
20 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,32 @@ | ||
import { userAtom } from "@/store/auth" | ||
import { useAtomValue } from "jotai" | ||
|
||
interface HeaderProps { | ||
onClick: () => void, | ||
id: string | ||
} | ||
|
||
export function Header({ onClick, id }: HeaderProps){ | ||
const user = useAtomValue(userAtom); | ||
|
||
return ( | ||
<header id={id} className="border border-green flex"> | ||
<button className='bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded' onClick={onClick}><div className='i-heroicons:bars-3 rounded-md px-3 py-3 ' /></button> | ||
<div className='justify-start py-1 pl-3 text-xl'>HoloDex</div> | ||
<div className='i-heroicons:chevron-down py-5'/> | ||
<button | ||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" | ||
onClick={onClick} | ||
> | ||
<div className="i-heroicons:bars-3 rounded-md px-3 py-3 " /> | ||
</button> | ||
<div className="justify-start py-1 pl-3 text-xl">HoloDex</div> | ||
<div className="i-heroicons:chevron-down py-5" /> | ||
<div className="flex flex-grow" /> | ||
{user ? ( | ||
<img | ||
src={`https://avatars.dicebear.com/api/jdenticon/${user.id}.svg`} | ||
/> | ||
) : ( | ||
<button>Login</button> | ||
)} | ||
</header> | ||
) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import { useToast } from "@/shadcn/ui/use-toast"; | ||
import { tokenAtom, userAtom } from "@/store/auth"; | ||
import { CredentialResponse } from "@react-oauth/google"; | ||
import { useMutation } from "@tanstack/react-query"; | ||
import { useSetAtom } from "jotai"; | ||
import { useCallback } from "react"; | ||
import { useNavigate } from "react-router-dom"; | ||
|
||
interface LoginResponse { | ||
jwt: string; | ||
user: User; | ||
} | ||
|
||
type LoginArgs = | ||
| { | ||
platform: "google"; | ||
error?: Error; | ||
credential: CredentialResponse; | ||
access_token?: never; | ||
jwt?: never; | ||
} | ||
| { | ||
platform: "discord"; | ||
error?: Error; | ||
credential?: never; | ||
access_token: string; | ||
jwt?: never; | ||
} | ||
| { | ||
platform: "twitter"; | ||
error?: Error; | ||
credential?: never; | ||
access_token?: never; | ||
jwt: string; | ||
}; | ||
|
||
export function useAuth() { | ||
const { toast } = useToast(); | ||
const navigate = useNavigate(); | ||
const setUser = useSetAtom(userAtom); | ||
const setToken = useSetAtom(tokenAtom); | ||
|
||
const login = useMutation( | ||
async ({ | ||
platform, | ||
error, | ||
credential, | ||
access_token, | ||
jwt: tempJWT, | ||
}: LoginArgs) => { | ||
switch (platform) { | ||
case "google": | ||
if (error) return onFailure(error); | ||
if (!credential.credential) | ||
return onFailure(new Error("Credential not provided")); | ||
try { | ||
const { jwt, user } = await getToken({ | ||
authToken: credential.credential, | ||
service: "google", | ||
}); | ||
setToken(jwt); | ||
setUser(user); | ||
navigate("/settings"); | ||
} catch (e) { | ||
onFailure(e as Error); | ||
} | ||
break; | ||
|
||
case "discord": | ||
if (error) return onFailure(error); | ||
try { | ||
const { jwt, user } = await getToken({ | ||
authToken: access_token, | ||
service: "discord", | ||
}); | ||
setToken(jwt); | ||
setUser(user); | ||
navigate("/settings"); | ||
} catch (e) { | ||
onFailure(e as Error); | ||
} | ||
|
||
break; | ||
|
||
case "twitter": | ||
if (error) return onFailure(error); | ||
try { | ||
const { jwt, user } = await getToken({ | ||
authToken: tempJWT, | ||
service: "twitter", | ||
}); | ||
setToken(jwt); | ||
setUser(user); | ||
navigate("/settings"); | ||
} catch (e) { | ||
onFailure(e as Error); | ||
} | ||
break; | ||
|
||
default: | ||
onFailure(Error("No login method specified")); | ||
|
||
break; | ||
} | ||
}, | ||
); | ||
|
||
const logout = useCallback(() => { | ||
setToken(null); | ||
setUser(null); | ||
}, [setToken, setUser]); | ||
|
||
const onFailure = useCallback( | ||
(err: Error) => { | ||
console.log("[Auth] Login error", err); | ||
toast({ | ||
variant: "destructive", | ||
title: "Error while logging in", | ||
}); | ||
setUser(null); | ||
setToken(null); | ||
}, | ||
[setToken, setUser, toast], | ||
); | ||
|
||
return { login, logout }; | ||
} | ||
|
||
export async function getToken({ | ||
authToken, | ||
service, | ||
jwt, | ||
}: { | ||
authToken: string; | ||
service: string; | ||
jwt?: string; | ||
}): Promise<LoginResponse> { | ||
const headers = { | ||
"content-type": "application/json", | ||
...(jwt && { Authorization: `Bearer ${jwt}` }), | ||
}; | ||
const body = { | ||
token: authToken, | ||
service, | ||
}; | ||
const res = await fetch(`/api/v2/user/login`, { | ||
method: "POST", | ||
headers, | ||
body: JSON.stringify(body), | ||
}); | ||
if (!res.ok) throw Error("Failed to acquire token"); | ||
return res.json(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { tokenAtom } from "@/store/auth"; | ||
import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; | ||
import { useAtomValue } from "jotai"; | ||
import { useCallback } from "react"; | ||
|
||
const axiosInstance = axios.create() | ||
|
||
export function useClient() { | ||
const token = useAtomValue(tokenAtom); | ||
|
||
const AxiosInstance = useCallback( | ||
function <T>( | ||
url: string, | ||
config?: AxiosRequestConfig, | ||
): Promise<AxiosResponse<T>> { | ||
const configWithUser: AxiosRequestConfig = { | ||
baseURL: `${window.location.protocol}//${window.location.host}/api/v2`, | ||
...config, | ||
headers: { | ||
...config?.headers, | ||
Authorization: `Bearer ${token}` | ||
}, | ||
}; | ||
return axiosInstance(url, configWithUser); | ||
}, | ||
[token], | ||
); | ||
|
||
return AxiosInstance | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { useLive } from "@/services/live.service" | ||
|
||
|
||
export function Home () { | ||
const { data } = useLive(); | ||
|
||
return ( | ||
<div className="w-full h-full"> | ||
{JSON.stringify(data)} | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { useAuth } from "@/hooks/useAuth"; | ||
import { Button } from "@/shadcn/ui/button"; | ||
import { GoogleLogin } from "@react-oauth/google"; | ||
import open from "oauth-open"; | ||
|
||
export function Login() { | ||
const { | ||
login: { mutate }, | ||
} = useAuth(); | ||
|
||
return ( | ||
<div className="w-full h-full"> | ||
<div className="flex-col gap-4"> | ||
<GoogleLogin | ||
onSuccess={(credential) => mutate({ platform: "google", credential })} | ||
onError={() => console.log("Google login failed")} | ||
/> | ||
<Button | ||
className="w-full" | ||
onClick={() => | ||
open( | ||
`https://discord.com/api/oauth2/authorize?client_id=793619250115379262&redirect_uri=${encodeURIComponent( | ||
`${window.location.protocol}//${window.location.host}/discord`, | ||
)}&response_type=token&scope=identify`, | ||
(error: Error, { access_token }: { access_token: string }) => | ||
mutate({ platform: "discord", error, access_token }), | ||
) | ||
} | ||
> | ||
Login with Discord | ||
</Button> | ||
{/* Twitter login is currently unavailable and is on hold */} | ||
{/* <Button | ||
className="w-full" | ||
onClick={() => | ||
(window.location.href = `${window.origin}/api/v2/user/login/twitter`) | ||
} | ||
> | ||
Login with Twitter | ||
</Button> */} | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.