use google user avatar as profile phone
This commit is contained in:
1
app/javascript/__generated__/graphql-schema.ts
generated
1
app/javascript/__generated__/graphql-schema.ts
generated
@@ -454,6 +454,7 @@ export type UpdateQuestionPayload = {
|
||||
|
||||
export type User = {
|
||||
__typename?: 'User';
|
||||
avatarUrl?: Maybe<Scalars['String']>;
|
||||
email: Scalars['String'];
|
||||
id: Scalars['ID'];
|
||||
name: Scalars['String'];
|
||||
|
||||
1
app/javascript/__generated__/schema.graphql
generated
1
app/javascript/__generated__/schema.graphql
generated
@@ -614,6 +614,7 @@ type UpdateQuestionPayload {
|
||||
}
|
||||
|
||||
type User {
|
||||
avatarUrl: String
|
||||
email: String!
|
||||
id: ID!
|
||||
name: String!
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import React, { FC, useState } from "react";
|
||||
import axios from "axios";
|
||||
|
||||
import { Alert } from "../Alert";
|
||||
import { Button } from "../Button";
|
||||
import { PhotoCrop } from "./PhotoCrop";
|
||||
import { useCurrentUser } from "../../contexts";
|
||||
import { Modal } from "../Modal";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean
|
||||
setIsOpen: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export const AvatarEditor: FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
const [croppedImage, setCroppedImage] = useState<any>()
|
||||
const [alert, setAlert] = useState<boolean>()
|
||||
const { refetch, authToken } = useCurrentUser()
|
||||
|
||||
const instance = axios.create({
|
||||
});
|
||||
|
||||
instance.defaults.headers.common.Authorization = `Bearer ${authToken}`;
|
||||
|
||||
const onSubmit = () => {
|
||||
instance
|
||||
.post("/update_avatar", {
|
||||
upload: croppedImage,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
setIsOpen(false)
|
||||
refetch()
|
||||
} else {
|
||||
setAlert(true);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setAlert(true);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Alterar Imagem de Perfil"
|
||||
isOpen={isOpen}
|
||||
setIsOpen={setIsOpen}
|
||||
buttons={
|
||||
<>
|
||||
<Button onClick={() => setIsOpen(false)}>
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => onSubmit()}>
|
||||
Salvar
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{alert && <Alert>Algo deu errado, tente novamente mais tarde.</Alert>}
|
||||
<PhotoCrop callback={setCroppedImage} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
import React, { FC, useState } from "react";
|
||||
import PhotoCropper from "react-avatar-edit";
|
||||
|
||||
type Props = {
|
||||
callback: (value: any) => void
|
||||
}
|
||||
|
||||
const borderStyle: React.CSSProperties = {
|
||||
textAlign: 'center',
|
||||
margin: 'auto',
|
||||
borderStyle: 'dotted',
|
||||
borderWidth: '0.3rem',
|
||||
borderRadius: '0.3rem',
|
||||
}
|
||||
|
||||
export const PhotoCrop: FC<Props> = ({ callback }) => {
|
||||
const [result, setResult] = useState<any>();
|
||||
const onCrop = (cropped: any) => {
|
||||
setResult(cropped);
|
||||
callback(result);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setResult(null);
|
||||
};
|
||||
|
||||
const onBeforeFileLoad = (elem: any) => {
|
||||
if (elem.target.files[0].size > 1000000) {
|
||||
elem.target.value = "";
|
||||
alert("A imagem selecionada é grande de mais!")
|
||||
}
|
||||
};
|
||||
|
||||
const dimention = 300;
|
||||
|
||||
return (
|
||||
<PhotoCropper
|
||||
borderStyle={borderStyle}
|
||||
label="Escolha uma imagem"
|
||||
width={dimention}
|
||||
height={dimention}
|
||||
imageWidth={dimention}
|
||||
imageHeight={dimention}
|
||||
onCrop={(e) => onCrop(e)}
|
||||
onClose={() => onClose()}
|
||||
onBeforeFileLoad={onBeforeFileLoad}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { AvatarEditor } from "./AvatarEditor";
|
||||
@@ -10,12 +10,19 @@ type Props = {
|
||||
export const UserAvatar: FC<Props> = ({user, className}) => {
|
||||
return (
|
||||
<div className={`rounded-full border-2 border-primary-light shadow ${className || ''}`}>
|
||||
<BoringAvatar
|
||||
size={"100%"}
|
||||
name={user.name}
|
||||
variant="pixel"
|
||||
colors={["#595F72", "#575D90", "#84A07C", "#C3D350", "#E6F14A"]}
|
||||
/>
|
||||
{user.avatarUrl ?
|
||||
<img
|
||||
className="rounded-full"
|
||||
src={user.avatarUrl}
|
||||
alt={`Avatar do usuário ${user.name}`}
|
||||
/>
|
||||
: <BoringAvatar
|
||||
size={"100%"}
|
||||
name={user.name}
|
||||
variant="pixel"
|
||||
colors={["#595F72", "#575D90", "#84A07C", "#C3D350", "#E6F14A"]}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ export * from "./Button";
|
||||
export * from "./Card";
|
||||
export * from "./CardGrid";
|
||||
export * from "./InputGroup";
|
||||
export * from "./AvatarEditor";
|
||||
export * from "./Navegator";
|
||||
export * from "./UserAvatar";
|
||||
export * from "./Dialog";
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
import React, {
|
||||
createContext, useContext, useState, FC
|
||||
} from "react";
|
||||
import { useQuery, gql } from "@apollo/client";
|
||||
import { gql, useQuery } from "@apollo/client";
|
||||
import React, { createContext, FC, useContext } from "react";
|
||||
|
||||
import { Query, UserRole } from "../__generated__/graphql-schema";
|
||||
import { UnauthorizedAccess } from "../pages/session";
|
||||
import { Loading } from "../pages/shared";
|
||||
import { Query, UserRole } from "../__generated__/graphql-schema";
|
||||
|
||||
export type UserContext = {
|
||||
user?: Query['currentUser']
|
||||
refetch: () => void
|
||||
isOnlyTeacher: boolean
|
||||
}
|
||||
user?: Query["currentUser"];
|
||||
isOnlyTeacher: boolean;
|
||||
};
|
||||
|
||||
const Context = createContext<UserContext>({
|
||||
refetch: () => {
|
||||
},
|
||||
isOnlyTeacher: false,
|
||||
})
|
||||
});
|
||||
|
||||
export const useCurrentUser = (): UserContext => {
|
||||
const context = useContext(Context);
|
||||
@@ -30,41 +25,33 @@ export const useCurrentUser = (): UserContext => {
|
||||
};
|
||||
|
||||
const CurrentUserQuery = gql`
|
||||
query CurrentUserQuery {
|
||||
currentUser {
|
||||
id
|
||||
name
|
||||
email
|
||||
roles
|
||||
}
|
||||
query CurrentUserQuery {
|
||||
currentUser {
|
||||
id
|
||||
name
|
||||
email
|
||||
roles
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
children: any
|
||||
}
|
||||
children: any;
|
||||
};
|
||||
|
||||
export const UserContext: FC<Props> = ({ children }) => {
|
||||
const [user, setUser] = useState<Query['currentUser']>();
|
||||
const isOnlyTeacher = !!(user?.roles.includes(UserRole.Teacher) && user?.roles.length === 1)
|
||||
const { loading, data } = useQuery<Query>(CurrentUserQuery);
|
||||
const user = data?.currentUser;
|
||||
const isOnlyTeacher = !!(
|
||||
user?.roles.includes(UserRole.Teacher) && user?.roles.length === 1
|
||||
);
|
||||
|
||||
const { refetch: refetchUserQuery, loading } = useQuery<Query>(CurrentUserQuery, {
|
||||
onCompleted: ({ currentUser }) => {
|
||||
setUser(currentUser)
|
||||
}
|
||||
})
|
||||
|
||||
const refetch = async () => {
|
||||
const { data: { currentUser } } = await refetchUserQuery()
|
||||
setUser(currentUser)
|
||||
}
|
||||
|
||||
if (loading) return <Loading />
|
||||
|
||||
if (!user) return <UnauthorizedAccess />
|
||||
if (loading) return <Loading />;
|
||||
if (!user?.roles.length) return <UnauthorizedAccess />;
|
||||
|
||||
return (
|
||||
<Context.Provider value={{ user, refetch, isOnlyTeacher }}>
|
||||
<Context.Provider value={{ user, isOnlyTeacher }}>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
);
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
|
||||
import { CurrentUserAvatar, Navigator } from "../../components";
|
||||
import { useCurrentUser } from "../../contexts";
|
||||
import { AvatarEditor, Navigator, CurrentUserAvatar } from "../../components";
|
||||
|
||||
export const Profile = () => {
|
||||
const [avatarEditorIsOpen, setAvatarEditorIsOpen] = useState(false);
|
||||
const { user } = useCurrentUser();
|
||||
|
||||
return (
|
||||
<>
|
||||
<AvatarEditor
|
||||
isOpen={avatarEditorIsOpen}
|
||||
setIsOpen={setAvatarEditorIsOpen}
|
||||
/>
|
||||
<Navigator home />
|
||||
<div className="bg-gray-100 w-full my-3">
|
||||
<main>
|
||||
<div className="flex items-center flex-col max-w-4xl m-auto">
|
||||
<div className="bg-white shadow border border-gray-100 flex flex-col items-center rounded p-4 w-full mt-12 mb-4 relative">
|
||||
<div
|
||||
className="w-20 absolute cursor-pointer"
|
||||
className="w-20 absolute"
|
||||
style={{ top: "-3.10rem" }}
|
||||
onClick={() => setAvatarEditorIsOpen(true)}
|
||||
>
|
||||
<CurrentUserAvatar />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user