From 838075c3d92e9ec64254de287e1fd59826cc69aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Wed, 10 Aug 2022 20:31:42 +0000 Subject: [PATCH] split appbar code --- app/javascript/components/Appbar/Appbar.tsx | 236 +----------------- .../components/Appbar/AppbarLogo.tsx | 16 ++ .../components/Appbar/AppbarTabs.tsx | 75 ++++++ .../components/Appbar/AppbarUserMenu.tsx | 156 ++++++++++++ .../FeaturesFromStep/FeaturesFormStep.tsx | 15 +- package.json | 2 + yarn.lock | 22 ++ 7 files changed, 286 insertions(+), 236 deletions(-) create mode 100644 app/javascript/components/Appbar/AppbarLogo.tsx create mode 100644 app/javascript/components/Appbar/AppbarTabs.tsx create mode 100644 app/javascript/components/Appbar/AppbarUserMenu.tsx diff --git a/app/javascript/components/Appbar/Appbar.tsx b/app/javascript/components/Appbar/Appbar.tsx index 526022b..640f7b6 100644 --- a/app/javascript/components/Appbar/Appbar.tsx +++ b/app/javascript/components/Appbar/Appbar.tsx @@ -1,239 +1,17 @@ -import React, { FC, Fragment, useState } from 'react' -import { useHistory, useLocation } from 'react-router'; -import { Menu, Transition } from '@headlessui/react' -import { ChartBarIcon, ClipboardListIcon } from '@heroicons/react/outline' +import React from 'react'; -import { Dialog } from '../Dialog' -import { useDispatch, useSelector } from 'react-redux'; -import { useCurrentUser } from '../../contexts'; -import { RootState } from '../../services/store'; -import { classNames } from '../../utils'; -import { DashboardRoutePaths, QuestionRoutePaths, SessionRoutePaths } from '../../routes' -import { turnOff } from '../../services/store/unsavedChanges'; -import { CurrentUserAvatar } from "../CurrentUserAvatar"; -import { localFetch } from '../../utils/localFetch'; -import { notEmpty } from '../../utils/notEmpty'; -import { UserRole } from '../../__generated__/graphql-schema'; - -const UserMenu: FC = () => { - const { user } = useCurrentUser(); - const history = useHistory(); - const [confirmLogout, setConfirmLogout] = useState(false) - const unsavedChanges = useSelector((state: RootState) => state.unsavedChanges) - const dispatch = useDispatch() - - const doLogout = () => { - setConfirmLogout(false) - - dispatch(turnOff()) - - localFetch('/users/sign_out', { - method: 'DELETE' - }).then(() => { - window.location.href = '/' - }) - } - - const handleLogout = () => { - if (unsavedChanges && !confirmLogout) { - setConfirmLogout(true) - } else { - doLogout() - } - } - - const [newPath, setNewPath] = useState() - - const handleForcedRedirect = () => { - if (!newPath) return - - dispatch(turnOff()) - setNewPath(undefined) - history.push(newPath) - } - - const handleLinkClick = (pathname: string) => { - if (unsavedChanges) { - setNewPath(pathname) - } else { - history.push(pathname) - } - } - - type MenuItem = { - onClick: Function - label: string - } - - const menuItems: MenuItem[] = [ - (user?.roles.includes(UserRole.Admin) && { - onClick: () => { window.location.href = '/admin'}, - label: 'Painel de Administração' - }), - { - onClick: () => { handleLinkClick(SessionRoutePaths.show) }, - label: 'Perfil' - }, - { - onClick: handleLogout, - label: 'Sair' - } - ].filter(notEmpty) - - return ( - <> - setNewPath(value ? newPath : undefined)} - onConfirmation={handleForcedRedirect} - title="Modificações não Salvas" - text="Todas as alterações serão descartadas. Deseja continuar?" - /> - - - {({ open }) => ( - <> - - - {user?.name} - -
- -
-
- - - {menuItems.map((item) => ( - - {({ active }) => ( - - {item.label} - - )} - - ))} - - - - )} -
- - ) -} - -const Links: FC = () => { - const unsavedChanges = useSelector((state: RootState) => state.unsavedChanges) - const dispatch = useDispatch() - const location = useLocation() - const history = useHistory() - - const [newPath, setNewPath] = useState() - - const handleForcedRedirect = () => { - if (!newPath) return - - dispatch(turnOff()) - setNewPath(undefined) - history.push(newPath) - } - - const handleLinkClick = (pathname: string) => { - if (unsavedChanges) { - setNewPath(pathname) - } else { - history.push(pathname) - } - } - - - const links = [{ - icon: , - tabel: 'Painel', - pathname: DashboardRoutePaths.index, - isCurrent: location.pathname.includes('dashboard'), - }, - { - icon: , - tabel: 'Edição', - pathname: QuestionRoutePaths.index, - isCurrent: location.pathname.includes('question'), - }] - - return ( - <> - setNewPath(value ? newPath : undefined)} - onConfirmation={handleForcedRedirect} - title="Modificações não Salvas" - text="Todas as alterações serão descartadas. Deseja continuar?" - /> -
- {links.map((link) => ( - - ))} -
- - ) -} - -const Logo: FC = () => ( -
- Símbolo do Unifeso - Logotipo do Unifeso -
-) +import { AppbarLogo } from './AppbarLogo'; +import { AppbarTabs } from './AppbarTabs'; +import { AppbarUserMenu } from './AppbarUserMenu'; export const Appbar = () => { return (
- - + +
- +
) } diff --git a/app/javascript/components/Appbar/AppbarLogo.tsx b/app/javascript/components/Appbar/AppbarLogo.tsx new file mode 100644 index 0000000..9fba487 --- /dev/null +++ b/app/javascript/components/Appbar/AppbarLogo.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +export const AppbarLogo = () => ( +
+ Símbolo do Unifeso + Logotipo do Unifeso +
+) diff --git a/app/javascript/components/Appbar/AppbarTabs.tsx b/app/javascript/components/Appbar/AppbarTabs.tsx new file mode 100644 index 0000000..a12188b --- /dev/null +++ b/app/javascript/components/Appbar/AppbarTabs.tsx @@ -0,0 +1,75 @@ +import { ChartBarIcon, ClipboardListIcon } from "@heroicons/react/outline"; +import React, { useState } from 'react'; +import { useDispatch, useSelector } from "react-redux"; +import { useHistory, useLocation } from 'react-router'; + +import { DashboardRoutePaths, QuestionRoutePaths } from "../../routes"; +import { RootState } from "../../services/store"; +import { turnOff } from "../../services/store/unsavedChanges"; +import { Dialog } from '../Dialog'; + +export const AppbarTabs = () => { + const unsavedChanges = useSelector((state: RootState) => state.unsavedChanges) + const dispatch = useDispatch() + const location = useLocation() + const history = useHistory() + + const [newPath, setNewPath] = useState() + + const handleForcedRedirect = () => { + if (!newPath) return + + dispatch(turnOff()) + + setNewPath(undefined) + history.push(newPath) + } + + const handleLinkClick = (pathname: string) => { + if (unsavedChanges) { + setNewPath(pathname) + } else { + history.push(pathname) + } + } + + + const links = [{ + icon: , + tabel: 'Painel', + pathname: DashboardRoutePaths.index, + isCurrent: location.pathname.includes('dashboard'), + }, + { + icon: , + tabel: 'Edição', + pathname: QuestionRoutePaths.index, + isCurrent: location.pathname.includes('question'), + }] + + return ( + <> + setNewPath(value ? newPath : undefined)} + onConfirmation={handleForcedRedirect} + title="Modificações não Salvas" + text="Todas as alterações serão descartadas. Deseja continuar?" + /> +
+ {links.map((link) => ( + + ))} +
+ + ) +} diff --git a/app/javascript/components/Appbar/AppbarUserMenu.tsx b/app/javascript/components/Appbar/AppbarUserMenu.tsx new file mode 100644 index 0000000..449a27d --- /dev/null +++ b/app/javascript/components/Appbar/AppbarUserMenu.tsx @@ -0,0 +1,156 @@ +import { Menu, Transition } from '@headlessui/react'; +import React, { Fragment, useState } from 'react'; +import { useHistory } from 'react-router'; +import { useDispatch, useSelector } from 'react-redux'; + +import { useCurrentUser } from '../../contexts'; +import { SessionRoutePaths } from '../../routes'; +import { RootState } from '../../services/store'; +import { turnOff } from '../../services/store/unsavedChanges'; +import { classNames } from '../../utils'; +import { localFetch } from '../../utils/localFetch'; +import { notEmpty } from '../../utils/notEmpty'; +import { UserRole } from '../../__generated__/graphql-schema'; +import { CurrentUserAvatar } from "../CurrentUserAvatar"; +import { Dialog } from '../Dialog'; + +export const AppbarUserMenu = () => { + const { user } = useCurrentUser(); + const history = useHistory(); + const [confirmLogout, setConfirmLogout] = useState(false) + const [newPath, setNewPath] = useState() + const unsavedChanges = useSelector((state: RootState) => state.unsavedChanges) + const dispatch = useDispatch() + + const doLogout = () => { + setConfirmLogout(false) + + dispatch(turnOff()) + + localFetch('/users/sign_out', { + method: 'DELETE' + }).then(() => { + window.location.href = '/' + }) + } + + const handleLogout = () => { + if (unsavedChanges && !confirmLogout) { + setConfirmLogout(true) + } else { + doLogout() + } + } + + + const handleForcedRedirect = () => { + if (!newPath) return + + dispatch(turnOff()) + setNewPath(undefined) + history.push(newPath) + } + + const handleLinkClick = (pathname: string) => { + if (unsavedChanges) { + setNewPath(pathname) + } else { + history.push(pathname) + } + } + + type MenuItem = { + onClick: Function + label: string + } + + const menuItems: MenuItem[] = [ + { + onClick: () => { handleLinkClick(SessionRoutePaths.show) }, + label: 'Perfil' + }, + { + onClick: handleLogout, + label: 'Sair' + } + ] + + if (user?.roles.includes(UserRole.Admin)) { + menuItems.push({ + onClick: () => { window.location.href = '/admin'}, + label: 'Painel de Administração' + }) + } + + return ( + <> + setNewPath(value ? newPath : undefined)} + onConfirmation={handleForcedRedirect} + title="Modificações não Salvas" + text="Todas as alterações serão descartadas. Deseja continuar?" + /> + + + {({ open }) => ( + <> + + + {user?.name} + +
+ +
+
+ + + {menuItems.map((item) => ( +
{ + item.onClick() + }} + > + + {({ active }) => ( + + {item.label} + + )} + +
+ ))} +
+
+ + )} +
+ + ) +} diff --git a/app/javascript/pages/question/Form/steps/FeaturesFromStep/FeaturesFormStep.tsx b/app/javascript/pages/question/Form/steps/FeaturesFromStep/FeaturesFormStep.tsx index 1efc2d7..34fe8ef 100644 --- a/app/javascript/pages/question/Form/steps/FeaturesFromStep/FeaturesFormStep.tsx +++ b/app/javascript/pages/question/Form/steps/FeaturesFromStep/FeaturesFormStep.tsx @@ -9,7 +9,7 @@ import { SubjectFragment, SubjectSelect } from "./SubjectSelect"; import { BLOOM_TAXONOMY, CHECK_TYPE, - DIFFICULTY, + DIFFICULTY } from "../../../../../utils/types"; export const FeaturesFragment = gql` @@ -27,20 +27,20 @@ export const FeaturesFragment = gql` } `; +const CURRENT_YEAR = new Date().getFullYear(); + export const FeaturesFormStep: FC = () => { const { - hooks: { setValue, register, getValues }, + hooks: { setValue, register, watch }, } = useFormProvider(); - const currentYear = new Date().getFullYear(); - - const authorship = getValues("authorship"); + const authorship = watch("authorship"); const [ownQuestion, setOwnQuestion] = useState(authorship === "UNIFESO"); const handleOwnCheck = (value: string) => { if (value === "UNIFESO") { setOwnQuestion(true); setValue("authorship", "UNIFESO"); - setValue("authorshipYear", currentYear.toString()); + setValue("authorshipYear", CURRENT_YEAR.toString()); } else { setOwnQuestion(false); setValue("authorship", ""); @@ -59,6 +59,7 @@ export const FeaturesFormStep: FC = () => {
{ className="w-full rounded p-1 border-gray-400 border shadow-sm" type="number" min="1999" - max={currentYear} + max={CURRENT_YEAR} step="1" readOnly={!!ownQuestion} /> diff --git a/package.json b/package.json index a50e1c6..ec39ac6 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "devDependencies": { "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6", + "@types/react-router": "^5.1.18", + "@types/react-router-dom": "^5.3.3", "autoprefixer": "^9.8.5", "postcss": "^7.0.32", "postcss-cli": "^7.1.1", diff --git a/yarn.lock b/yarn.lock index 9821ee2..49458b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -366,6 +366,11 @@ redux-thunk "^2.4.1" reselect "^4.1.5" +"@types/history@^4.7.11": + version "4.7.11" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" + integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== + "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -386,6 +391,23 @@ dependencies: "@types/react" "*" +"@types/react-router-dom@^5.3.3": + version "5.3.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" + integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*", "@types/react-router@^5.1.18": + version "5.1.18" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.18.tgz#c8851884b60bc23733500d86c1266e1cfbbd9ef3" + integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react@*", "@types/react@^18.0.15": version "18.0.15" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.15.tgz#d355644c26832dc27f3e6cbf0c4f4603fc4ab7fe"