Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds current subject to sidebar and some small styling changes #723

Merged
merged 6 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions apps/web/src/components/Layout/LanguageToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import { useNotificationsStore } from '@douglasneuroinformatics/ui';
import { cn, useNotificationsStore } from '@douglasneuroinformatics/ui';
import { LanguageIcon } from '@heroicons/react/24/solid';
import type { Language } from '@open-data-capture/common/core';
import { useTranslation } from 'react-i18next';

Expand All @@ -17,7 +18,7 @@ type LanguageToggleProps = {
onClick?: React.MouseEventHandler<HTMLButtonElement>;
} & React.ComponentPropsWithoutRef<'button'>;

export const LanguageToggle = ({ onClick, ...props }: LanguageToggleProps) => {
export const LanguageToggle = ({ className, onClick, ...props }: LanguageToggleProps) => {
const notifications = useNotificationsStore();
const { i18n, t } = useTranslation('common');

Expand All @@ -36,7 +37,8 @@ export const LanguageToggle = ({ onClick, ...props }: LanguageToggleProps) => {
};

return (
<button onClick={(e) => void handleClick(e)} {...props}>
<button className={cn('flex items-center', className)} onClick={(e) => void handleClick(e)} {...props}>
<LanguageIcon className="mr-2" height={16} width={16} />
{inactiveLanguage ? languages[inactiveLanguage].nativeName : 'ERROR'}
</button>
);
Expand Down
27 changes: 3 additions & 24 deletions apps/web/src/components/Layout/NavButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,20 @@ export type NavButtonProps = {
isActive: boolean;
label: string;
onClick?: () => void;
variant: 'horizontal' | 'vertical';
};

export const NavButton = ({
activeClassName,
className,
icon: Icon,
isActive,
label,
variant,
...props
}: NavButtonProps) => {
export const NavButton = ({ activeClassName, className, icon: Icon, isActive, label, ...props }: NavButtonProps) => {
return (
<button
className={cn(
'flex w-full items-center p-2 text-slate-700 hover:text-slate-900 disabled:opacity-75 disabled:hover:cursor-not-allowed dark:text-slate-300 dark:hover:text-slate-100',
{
'justify-start': variant === 'vertical',
'mx-1 justify-center': variant === 'horizontal'
},
'flex w-full items-center justify-start p-2 text-slate-700 hover:text-slate-900 disabled:opacity-75 disabled:hover:cursor-not-allowed dark:text-slate-300 dark:hover:text-slate-100',
className,
isActive && (activeClassName ?? 'text-slate-900 dark:text-slate-100')
)}
type="button"
{...props}
>
{Icon && (
<Icon
className={cn('mr-2', {
hidden: variant === 'horizontal'
})}
height={16}
width={16}
/>
)}
{Icon && <Icon className="mr-2" height={16} width={16} />}
{label}
</button>
);
Expand Down
17 changes: 9 additions & 8 deletions apps/web/src/components/Layout/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ export const Navigation = ({ btn, isAlwaysDark, onNavigate, orientation }: Navig
const location = useLocation();

useEffect(() => {
const globalItems: NavItem[] = [
{
currentUser?.ability.can('read', 'Summary');
const globalItems: NavItem[] = [];
if (currentUser?.ability.can('read', 'Summary')) {
globalItems.push({
'data-cy': 'overview',
icon: ChartBarIcon,
id: '/overview',
label: t('navLinks.overview')
}
];
});
}
if (currentUser?.ability.can('read', 'Subject') && currentUser.ability.can('read', 'InstrumentRecord')) {
globalItems.push({
'data-cy': 'view-subjects',
Expand Down Expand Up @@ -98,13 +100,13 @@ export const Navigation = ({ btn, isAlwaysDark, onNavigate, orientation }: Navig
{navItems.map((items, i) => (
<div className="w-full py-2 first:pt-0 last:pb-0" key={i}>
<>
{items.map(({ id, ...props }) => (
{items.map(({ disabled, id, ...props }) => (
<NavButton
activeClassName={btn?.activeClassName}
className={btn?.className}
disabled={disabled && location.pathname !== id}
isActive={location.pathname === id}
key={id}
variant={orientation}
onClick={() => {
navigate(id);
onNavigate?.(id);
Expand All @@ -119,7 +121,6 @@ export const Navigation = ({ btn, isAlwaysDark, onNavigate, orientation }: Navig
icon={StopIcon}
isActive={false}
label={t('navLinks.endVisit')}
variant={orientation}
onClick={() => {
setIsEndVisitModalOpen(true);
}}
Expand All @@ -139,7 +140,7 @@ export const Navigation = ({ btn, isAlwaysDark, onNavigate, orientation }: Navig
onClick={() => {
setActiveVisit(null);
setIsEndVisitModalOpen(false);
navigate('/overview');
navigate('/visits/add-visit');
}}
/>
<Button
Expand Down
33 changes: 32 additions & 1 deletion apps/web/src/components/Layout/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { ThemeToggle } from '@douglasneuroinformatics/ui';
import { toBasicISOString } from '@douglasneuroinformatics/utils';
import { toLowerCase } from '@open-data-capture/common/core';
import { Branding } from '@open-data-capture/react-core';
import { AnimatePresence, motion } from 'framer-motion';
import { useTranslation } from 'react-i18next';

import { useActiveVisitStore } from '@/stores/active-visit-store';

import { Navigation } from './Navigation';
import { UserDropup } from './UserDropup';

export const Sidebar = () => {
const { activeVisit } = useActiveVisitStore();
const { t } = useTranslation(['core', 'common']);
return (
<div className="flex h-screen w-80 flex-col bg-slate-900 p-3 text-slate-300 shadow-lg dark:border-r dark:border-slate-700">
<Branding className="h-14 md:p-2" logoVariant="light" />
Expand All @@ -17,7 +25,30 @@ export const Sidebar = () => {
isAlwaysDark={true}
orientation="vertical"
/>
<hr className="my-1 mt-auto h-[1px] border-none bg-slate-700" />
<hr className="invisible mt-auto" />
<AnimatePresence>
{activeVisit && (
<motion.div
animate={{ opacity: 1 }}
className="my-3 rounded-md border border-slate-700 bg-slate-800 p-2 tracking-tight"
exit={{ opacity: 0 }}
initial={{ opacity: 0 }}
>
<h3 className="font-medium">{t('common:currentSubject', { context: activeVisit.subject.sex })}</h3>
<hr className="my-1.5 h-[1px] border-none bg-slate-700" />
<div className="text-sm">
<p>{`${t('fullName')}: ${activeVisit.subject.firstName} ${activeVisit.subject.lastName}`}</p>
<p>
{`${t('identificationData.dateOfBirth.label')}: ${toBasicISOString(activeVisit.subject.dateOfBirth)}`}{' '}
</p>
<p>
{`${t('identificationData.sex.label')}: ${t(`core:identificationData.sex.${toLowerCase(activeVisit.subject.sex)}`)}`}
</p>
</div>
</motion.div>
)}
</AnimatePresence>
<hr className="my-1 h-[1px] border-none bg-slate-700" />
<div className="flex items-center">
<UserDropup />
<ThemeToggle className="hover:backdrop-brightness-150" />
Expand Down
16 changes: 11 additions & 5 deletions apps/web/src/components/Layout/UserDropup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useRef, useState } from 'react';

import { ArrowToggle, useOnClickOutside } from '@douglasneuroinformatics/ui';
import { Transition } from '@headlessui/react';
import { UserCircleIcon } from '@heroicons/react/24/solid';
import { AdjustmentsVerticalIcon, LockClosedIcon, UserCircleIcon } from '@heroicons/react/24/solid';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';

Expand Down Expand Up @@ -39,17 +39,23 @@ export const UserDropup = () => {
leaveTo="transform opacity-0 scale-95"
show={isOpen}
>
<div className="absolute bottom-3 w-40 bg-slate-800 shadow-lg">
<div className="absolute bottom-3 w-44 overflow-hidden rounded-md border border-slate-700 bg-slate-800 tracking-tight shadow-lg">
<button
className="w-full p-2 hover:bg-slate-700"
className="flex w-full items-center px-3 py-2 hover:bg-slate-700"
onClick={() => {
auth.logout();
}}
>
<LockClosedIcon className="mr-2" height={16} width={16} />
{t('userDropup.logout')}
</button>
<LanguageToggle className="w-full p-2 hover:bg-slate-700" onClick={closeDropup} />
<Link className="block w-full p-2 text-center hover:bg-slate-700" to="/user" onClick={closeDropup}>
<LanguageToggle className="w-full px-3 py-2 text-left hover:bg-slate-700" onClick={closeDropup} />
<Link
className="flex w-full items-center px-3 py-2 text-left hover:bg-slate-700"
to="/user"
onClick={closeDropup}
>
<AdjustmentsVerticalIcon className="mr-2" height={16} width={16} />
{t('userDropup.preferences')}
</Link>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/features/auth/components/DemoModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const DemoModal = ({ isOpen, onClose, onLogin }: DemoModalProps) => {
<h5 className="font-semibold">{t('demo.availableUsers')}</h5>
<p className="text-default text-sm leading-tight">{t('demo.pleaseSelectUser')}</p>
</div>
<Card className="divide-y divide-slate-200 dark:divide-slate-600">
<Card className="-mx-1 divide-y divide-slate-200 dark:divide-slate-600">
{DEMO_USERS.map((user) => (
<div className="flex items-center space-x-4 px-2 py-3" key={user.username}>
<div className="text-default min-w-0 flex-1">
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/features/auth/components/LoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const LoginButton = ({ onClick }: LoginButtonProps) => {
</motion.div>
</AnimatePresence>
<button
className="text-default flex items-center gap-2 rounded-lg border border-slate-300 bg-white px-4 py-1 text-sm font-medium leading-5 shadow-sm hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:hover:bg-slate-700"
className="text-default flex items-center gap-2 rounded-md border border-slate-300 bg-white px-4 py-1.5 text-sm font-medium leading-5 shadow-sm hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:hover:bg-slate-700"
type="button"
onClick={onClick}
onMouseEnter={() => setShowInfo(true)}
Expand Down
7 changes: 6 additions & 1 deletion apps/web/src/features/overview/pages/OverviewPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useTranslation } from 'react-i18next';
import { Navigate } from 'react-router-dom';

import { PageHeader } from '@/components/PageHeader';
import { useAuthStore } from '@/stores/auth-store';
Expand All @@ -13,6 +14,10 @@ export const OverviewPage = () => {

const pageTitle = currentUser?.firstName ? `${t('welcome')}, ${currentUser.firstName}` : t('welcome');

if (!currentUser?.ability.can('read', 'Summary')) {
return <Navigate to="/visits/add-visit" />;
}

return (
<div className="flex flex-grow flex-col">
<Disclaimer isRequired={import.meta.env.PROD} />
Expand All @@ -22,7 +27,7 @@ export const OverviewPage = () => {
<h3 className="text-center text-xl font-medium lg:text-left">{t('summary')}</h3>
<GroupSwitcher />
</div>
{currentUser?.ability.can('read', 'Summary') && <Summary />}
<Summary />
</section>
</div>
);
Expand Down
12 changes: 12 additions & 0 deletions apps/web/src/translations/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@
"fr": "Utilisateur standard"
}
},
"currentSubject": {
"en": "Current Subject",
"fr": "Le client actuel"
},
"currentSubject_FEMALE": {
"en": "Current Subject",
"fr": "La cliente actuelle"
},
"currentSubject_MALE": {
"en": "Current Subject",
"fr": "Le client actuel"
},
"errors": {
"failedToChangeLanguage": {
"en": "Failed to change languages",
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/translations/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
},
"endVisitModal": {
"message": {
"en": "Are you sure you want to end the current visit? If you choose to proceed, you'll be taken back to the overview page.",
"fr": "Êtes-vous sûr de vouloir mettre fin à la visite en cours ? Si vous décidez de continuer, vous serez ramené à la page de vue d'ensemble."
"en": "Are you sure you want to end the current visit? If you choose to proceed, you'll be taken back to the begin visit page.",
"fr": "Êtes-vous sûr de vouloir mettre fin à la visite en cours ? Si vous décidez de continuer, vous serez ramené à la page de commencement d'une visite."
},
"title": {
"en": "End Visit",
Expand Down
Loading