Merge pull request #41 from MR-medreport/MED-111

feat(MED-111): update navigation links and adjust invitation handling
This commit is contained in:
danelkungla
2025-08-04 18:35:08 +03:00
committed by GitHub
10 changed files with 77 additions and 39 deletions

View File

@@ -22,10 +22,6 @@ const links = {
label: 'marketing:documentation', label: 'marketing:documentation',
path: '/docs', path: '/docs',
}, },
Pricing: {
label: 'marketing:pricing',
path: '/pricing',
},
FAQ: { FAQ: {
label: 'marketing:faq', label: 'marketing:faq',
path: '/faq', path: '/faq',

View File

@@ -25,7 +25,7 @@ const MembershipConfirmationNotification: React.FC<{
descriptionKey="account:membershipConfirmation:successDescription" descriptionKey="account:membershipConfirmation:successDescription"
buttonProps={{ buttonProps={{
buttonTitleKey: 'account:membershipConfirmation:successButton', buttonTitleKey: 'account:membershipConfirmation:successButton',
href: pathsConfig.app.selectPackage, href: pathsConfig.app.home,
}} }}
/> />
); );

View File

@@ -8,7 +8,7 @@ import { withI18n } from '~/lib/i18n/with-i18n';
import MembershipConfirmationNotification from './_components/membership-confirmation-notification'; import MembershipConfirmationNotification from './_components/membership-confirmation-notification';
async function UpdateAccountSuccess() { async function MembershipConfirmation() {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const { const {
@@ -22,4 +22,4 @@ async function UpdateAccountSuccess() {
return <MembershipConfirmationNotification userId={user.id} />; return <MembershipConfirmationNotification userId={user.id} />;
} }
export default withI18n(UpdateAccountSuccess); export default withI18n(MembershipConfirmation);

View File

@@ -108,7 +108,7 @@ async function JoinTeamAccountPage(props: JoinTeamAccountPageProps) {
const signOutNext = `${pathsConfig.auth.signIn}?invite_token=${token}`; const signOutNext = `${pathsConfig.auth.signIn}?invite_token=${token}`;
// once the user accepts the invitation, we redirect them to the account home page // once the user accepts the invitation, we redirect them to the account home page
const accountHome = pathsConfig.app.home; const membershipConfirmation = pathsConfig.auth.membershipConfirmation;
const email = auth.data.email ?? ''; const email = auth.data.email ?? '';
@@ -120,7 +120,7 @@ async function JoinTeamAccountPage(props: JoinTeamAccountPageProps) {
invitation={invitation} invitation={invitation}
paths={{ paths={{
signOutNext, signOutNext,
accountHome, membershipConfirmation,
}} }}
/> />
</AuthLayoutShell> </AuthLayoutShell>

View File

@@ -30,7 +30,6 @@ function getPaths() {
'/faq', '/faq',
'/blog', '/blog',
'/docs', '/docs',
'/pricing',
'/contact', '/contact',
'/cookie-policy', '/cookie-policy',
'/terms-of-service', '/terms-of-service',

View File

@@ -222,12 +222,13 @@ export function NotificationsPopover(params: {
</div> </div>
</div> </div>
<div className={'py-2'}> <div className="py-2">
<Button <Button
className={'max-h-6 max-w-6'} className="max-h-6 max-w-6"
size={'icon'} size="icon"
variant={'ghost'} variant="ghost"
onClick={() => { onClick={() => {
console.log('test');
setNotifications((existing) => { setNotifications((existing) => {
return existing.filter( return existing.filter(
(existingNotification) => (existingNotification) =>
@@ -238,7 +239,7 @@ export function NotificationsPopover(params: {
return dismissNotification(notification.id); return dismissNotification(notification.id);
}} }}
> >
<XIcon className={'h-3'} /> <XIcon className="h-3" />
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,6 @@
import Image from 'next/image'; import Image from 'next/image';
import { useDismissNotification } from '@kit/notifications/hooks';
import { Heading } from '@kit/ui/heading'; import { Heading } from '@kit/ui/heading';
import { If } from '@kit/ui/if'; import { If } from '@kit/ui/if';
import { Separator } from '@kit/ui/separator'; import { Separator } from '@kit/ui/separator';
@@ -25,7 +26,7 @@ export function AcceptInvitationContainer(props: {
paths: { paths: {
signOutNext: string; signOutNext: string;
accountHome: string; membershipConfirmation: string;
}; };
}) { }) {
return ( return (
@@ -42,36 +43,36 @@ export function AcceptInvitationContainer(props: {
<If condition={props.invitation.account.picture_url}> <If condition={props.invitation.account.picture_url}>
{(url) => ( {(url) => (
<Image <Image
alt={`Logo`} alt="Logo"
src={url} src={url}
width={64} width={64}
height={64} height={64}
className={'object-cover'} className="object-cover"
/> />
)} )}
</If> </If>
<div className={'text-muted-foreground text-center text-sm'}> <div className="text-muted-foreground text-center text-sm">
<Trans <Trans
i18nKey={'teams:acceptInvitationDescription'} i18nKey="teams:acceptInvitationDescription"
values={{ values={{
accountName: props.invitation.account.name, accountName: props.invitation.account.name,
}} }}
/> />
</div> </div>
<div className={'flex flex-col space-y-4'}> <div className="flex flex-col space-y-4">
<form <form
data-test={'join-team-form'} data-test="join-team-form"
className={'w-full'} className="w-full"
action={acceptInvitationAction} action={acceptInvitationAction}
> >
<input type="hidden" name={'inviteToken'} value={props.inviteToken} /> <input type="hidden" name="inviteToken" value={props.inviteToken} />
<input <input
type={'hidden'} type="hidden"
name={'nextPath'} name="nextPath"
value={props.paths.accountHome} value={props.paths.membershipConfirmation}
/> />
<InvitationSubmitButton <InvitationSubmitButton
@@ -84,8 +85,8 @@ export function AcceptInvitationContainer(props: {
<SignOutInvitationButton nextPath={props.paths.signOutNext} /> <SignOutInvitationButton nextPath={props.paths.signOutNext} />
<span className={'text-muted-foreground text-center text-xs'}> <span className="text-muted-foreground text-center text-xs">
<Trans i18nKey={'teams:signInWithDifferentAccountDescription'} /> <Trans i18nKey="teams:signInWithDifferentAccountDescription" />
</span> </span>
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
drop function if exists medreport.add_invitations_to_account(text, medreport.invitation[]); drop function if exists medreport.add_invitations_to_account(text, invitation[]);
drop type if exists medreport.invitation; drop type if exists medreport.invitation;

View File

@@ -0,0 +1,45 @@
grant
execute on function medreport.accept_invitation (text, uuid) to service_role;
CREATE OR REPLACE FUNCTION medreport.accept_invitation(token text, user_id uuid)
RETURNS uuid
LANGUAGE plpgsql
SET search_path TO ''
AS $function$declare
target_account_id uuid;
target_role varchar(50);
begin
select
account_id,
role into target_account_id,
target_role
from
medreport.invitations
where
invite_token = token
and expires_at > now();
if not found then
raise exception 'Invalid or expired invitation token';
end if;
insert into medreport.accounts_memberships(
user_id,
account_id,
account_role)
values (
accept_invitation.user_id,
target_account_id,
target_role);
delete from medreport.invitations
where invite_token = token;
update medreport.notifications
set dismissed = true
where link ilike '%' || token || '%';
return target_account_id;
end;$function$
;

View File

@@ -1,4 +1,4 @@
-- Create analysis for /home/analysis-results -- CREATE NEW ANALYSIS START
INSERT INTO medreport.analysis_groups ( INSERT INTO medreport.analysis_groups (
id, id,
original_id, original_id,
@@ -68,10 +68,10 @@ VALUES (
1 -- parent_analysis_element_id 1 -- parent_analysis_element_id
); );
-- CREATE NEW ANALYSIS END
-- CREATE NEW ANALYSIS RESPONSE START
INSERT INTO medreport.analysis_orders ( INSERT INTO medreport.analysis_orders (
analysis_element_ids, analysis_element_ids,
@@ -101,12 +101,6 @@ VALUES (
'COMPLETED', 'COMPLETED',
'8dcb4354-77be-4915-a2cd-8fc573e675d6' '8dcb4354-77be-4915-a2cd-8fc573e675d6'
) )
ON CONFLICT (order_number)
DO UPDATE SET
analysis_order_id = EXCLUDED.analysis_order_id,
order_status = EXCLUDED.order_status,
user_id = EXCLUDED.user_id
RETURNING id;
INSERT INTO medreport.analysis_response_elements ( INSERT INTO medreport.analysis_response_elements (
id, id,
@@ -144,3 +138,5 @@ VALUES
NOW(), NOW(),
'Hematokrit' 'Hematokrit'
); );
-- CREATE NEW ANALYSIS RESPONSE END