From 83f447eeb145ff7269b50d24061c74a1bccbb046 Mon Sep 17 00:00:00 2001 From: Nathan Gong Date: Thu, 19 Oct 2023 12:46:43 -0500 Subject: [PATCH] Create email invite confirmation screen (#215) ### Summary Resolves #205 Creates a confirmation screen for email invite, access through /confirm-invite ### Checklist #### UI Requirements ~~- [ ] Information about the invitation (i.e., the author of the schedule, its name, and the account that is given access to this schedule) is displayed.~~ -- Figma doesn't specify any of this information (?) #### Functional Requirements - [x] The screen automatically redirects after 30s. - [x] Works for preview sites. ### How to Test Run it locally and navigate to http://localhost:3000/confirm-invite --------- Co-authored-by: Samarth Chandna <57265280+samarth52@users.noreply.github.com> Co-authored-by: Samarth Chandna --- public/bitsOfGood.png | Bin 2404 -> 0 bytes public/bitsOfGood.svg | 12 +++ src/components/InviteBackLink/index.tsx | 98 ++++++++++++++---- src/components/InviteBackLink/stylesheet.scss | 79 ++++++++++++++ 4 files changed, 171 insertions(+), 18 deletions(-) delete mode 100644 public/bitsOfGood.png create mode 100644 public/bitsOfGood.svg create mode 100644 src/components/InviteBackLink/stylesheet.scss diff --git a/public/bitsOfGood.png b/public/bitsOfGood.png deleted file mode 100644 index 3c1115d310cbce138bd6b8fe6b7565d54c65ebec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2404 zcmV-q37htbP)^00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPD4wK~#7F?Op$M z+cprs?gU~ch&PZjfzt`7OyG0^sT0_pKGG^dP=jPr$1;u}0+Ez*oKGBVB!LU9X`Y8;~y>4Gvc zGR^~PCN`nYvvfwr89>d-Hq?}nkue#5q2X9N@>i7cW}uc;(h|E;w;GXtynFZVfig}P z;>9gov$9B^F!2tzsBbxjbs(1uvMqTZ;22USYLDcg=?4{MB!iN3AKQNZdm4t7Bfk*o zUZh=DsT=_4452z?BhpT!@8bHBG9DphQHYQ4)b@uw(7iB%m05M}g2GUWv{5tm*(kM| ziC4W_1?A;KA4B>=#z+WSGpmvK3k^p>tx}ibb0yYO|I#agXwxk{pPe?MegDuah3X4S zc6%?)eBCnTE6|lRaLQx~J>k1>Rnb|t!VB#6a{`Rw6R`>$?eUt2p91%#hW`=$w zjzK}~n);;IT4HwnDn5P_>35Mnye4ZR5(T^7W!bzeLe|V%N{@ovF0L1cbgziC&u*5C zQ-;@?S(%K52dV7rJM}5)rO(kd^InVcKM6(on?{7P04^0@lD~&jS<^!Aqix2V>6A%a zs>=se-w!$=D7i@YX1D&{$I4_3S)=uEbmc|Ka*Q_f3Tn95zYD{&3!mpH0iank!|n$) z@@;ARqL=53t)c8WTDP51E=aiccF3ZuZw>RlKm~scwz$NzmlnB5_uvez?E2U`%ACV4 zYnkUQYxv1h=6mfUppB^9T6mkmv1azEWC1&B7sD_g$mkyGuju?B~EwK z&v%r$2HVv)$ZC-F0{wtob$lrvCBOV#*L}Xw%C2kEEu-Dyxjcfs6wtqu+a8}+FuyyU z^`jdc^!-!mq#jD>K|9WzY*#j3p~iQ@&1_D>Aq3 z;G%`6|2Tl|O2eaR)ZQ|>A+z0FQ{PPhtx0|rql@x(1lFy4cRFR>GMXBOK89n3KHzwO zT_8@D3r#yX)-alE??S%7w?EZObPmOlHLo=2=nMgGKSuG#e_P?k$} zt+TXNq%W@_N1KNpw2(LlpR0?<9lIW69tNUe*N?lRIzs8L6X|m=eWh@e?0Vy%=lRmy znUlXxf6L9O=|k+b5_ zvc*%zTrQ)^#L$moEx#d((y;43UpiS@c{D65FAU#x^#|d-2QxN?Zzv2l`W?LysP)fB zvYWi6%5U)c5Bckq`9RYnWDtuTY;@&EmFcr)zPIFkL4co`>>Er`CdRozDzsb&i?1K3 zmCKIIFLQ;+-Qp8R3dL}hImEiK@pVee#Ygxk^Tv`V8?=Kv0!#)UxH{uEnivyob~&Mx z`Y(|_iqxIXlIC{9NXr2;^pQ#JIrtW?a#F%z0bWrYhA1W8*hRDuBQc!COu6aj68>S{Z;GXOoOD}bNP8VkPq85TWoh98JQmJ<=yQBapb3RB( z3>!Vs0X-gQ*mbNj8#l8o;51G5#UM*pnC9HUSHtqgRc3{i2hEaNr9P;gS-IxfdpG@2$LP6a*P|bE#Bp%RCmo&QgIg;Fg@bqMFAjRXud$zKpxv?SrGvh30;w2Cpa@TsjIdRfbe=%#6@IS2rAGcIB270GO9+L9+C0^Cgb=d7icT9YsP3Kz8se^50rt zO5Z9?48`k(N^)m$6gL!F_fDbeX~?llu3q?6kGBW)OhY39PocF1J^gOgi@N1F(C#pI z=`p6glOx)V)Bf)BMg`%x%GAkv7vsf9Da#&z1x?ToOicKijY-$Z8E+Gs88P>(Sg5Jr zcT+42Ji`jKrfKD%(QRs#lo1Em*L+!#GrWQ4eswuP%vpZ-ian79dmtZe|M5`Uci%!ubX|Pt48*z{J&pgLzzi;c@2}1k&%&+k&%({w(&oj Wm$Bn + + + + + + + + + + + diff --git a/src/components/InviteBackLink/index.tsx b/src/components/InviteBackLink/index.tsx index e05d8a02..105259ca 100644 --- a/src/components/InviteBackLink/index.tsx +++ b/src/components/InviteBackLink/index.tsx @@ -1,34 +1,96 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import axios from 'axios'; -// import { CLOUD_FUNCTION_BASE_URL } from '../../constants'; +import { CLOUD_FUNCTION_BASE_URL } from '../../constants'; +import Spinner from '../Spinner'; -const handleInvite = async (inviteId: string | undefined): Promise => - // The link should be changed to prod link, or we can choose the link based - // on environment - axios.post( - `http://127.0.0.1:5001/gt-scheduler-web-dev/us-central1/handleFriendInvitation`, - { inviteId } - ); -// .then((res) => { -// console.log(res); -// }) -// .catch((err) => { -// console.error(err); -// }); +import './stylesheet.scss'; + +// eslint-disable-next-line no-shadow +enum LoadingState { + LOADING, + SUCCESS, + ERROR, +} + +const url = `${CLOUD_FUNCTION_BASE_URL}/handleFriendInvitation`; + +const handleInvite = async (inviteId: string | undefined): Promise => { + const requestData = JSON.stringify({ inviteId }); + await axios({ + method: 'POST', + url, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + data: `data=${requestData}`, + }); +}; export default function InviteBackLink(): React.ReactElement { const navigate = useNavigate(); const { id } = useParams(); + const [state, setState] = useState(LoadingState.LOADING); useEffect(() => { if (id && navigate) { handleInvite(id) - .then(() => navigate('/')) - .catch(() => navigate('/')); + .then(() => { + setState(LoadingState.SUCCESS); + setTimeout(() => { + navigate('/'); + }, 5000); + }) + .catch(() => { + setState(LoadingState.ERROR); + setTimeout(() => { + navigate('/'); + }, 10000); + }); } }, [id, navigate]); - return
; + if (state === LoadingState.LOADING) { + return ( +
+ +

Loading

+
friend schedule invite
+
+ ); + } + + return ( +
+ {state === LoadingState.SUCCESS ? ( +

Congratulations on Adding a New Schedule to your View!

+ ) : ( +

We've Encountered an Error, Please Try Again

+ )} +

You are being redirected to our main site, please wait...

+

+ If you have not been redirected in 30 seconds, please click the button + below +

+ + + + Bits of Good Logo + +
+ ); } diff --git a/src/components/InviteBackLink/stylesheet.scss b/src/components/InviteBackLink/stylesheet.scss new file mode 100644 index 00000000..22368c54 --- /dev/null +++ b/src/components/InviteBackLink/stylesheet.scss @@ -0,0 +1,79 @@ +@import '../../variables'; + +body { + background-color: $theme-dark-background; + color: $theme-dark-foreground; +} + +.Loading { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + height: 100%; + + h4 { + font-size: 1.4rem; + margin-top: 12px; + margin-bottom: 8px; + } +} + +.EmailInviteConfirmation { + display: flex; + flex-direction: column; + align-items: center; + padding-top: 20vh; + padding-left: 32px; + padding-right: 32px; + font-size: 24px; + height: 100%; + text-align: center; + + @media (max-width: 720px) { + padding-top: 60px; + } + + @media (max-width: 450px) { + padding-top: 60px; + font-size: 18px; + } + + @media (max-width: 300px) { + font-size: 16px; + } + + @media (max-height: 600px) { + padding-top: 60px; + } + + h1 { + font-size: 36px; + font-weight: 600; + + @media (max-width: 450px) { + font-size: 30px; + } + + @media (max-width: 300px) { + font-size: 24px; + } + } + + .footer { + position: absolute; + bottom: 38px; + } + + .continue-button { + background-color: #fe7c53; + color: white; + margin-top: 96px; + padding: 8px 24px; + border: none; + border-radius: 16px; + cursor: pointer; + font-size: 24px; + font-weight: 600; + } +}