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

feat: improve onboarding experience and fix unable to sign up bug #630

Merged
merged 3 commits into from
Jul 8, 2023
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
File renamed without changes.
5 changes: 5 additions & 0 deletions apps/web/locales/en/ws-members.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"description": "Manage members of your workspace.",
"invite_member": "Invite member",
"enter_email_or_username": "Enter an email or username",
"member_since": "Member since",
"pending_invitations": "Pending invitations",
"invited": "Invited",
Expand All @@ -9,11 +10,15 @@
"remove_member": "Remove member",
"member_removed": "Member removed",
"revoke_invitation": "Revoke invitation",
"invitation_sent": "Invitation sent",
"invitation_revoked": "Invitation revoked",
"invitation_to": "Invitation to",
"has_been_sent": "has been sent",
"has_been_revoked": "has been revoked",
"has_been_removed": "has been removed from this workspace",
"error": "Error",
"invitation_error": "An error occurred while sending the invitation",
"invitation_error_already_exist": "User is already a member or invite has been sent",
"revoke_error": "An error occurred while revoking the invitation",
"remove_error": "An error occurred while removing the member",
"member-settings": "Member settings",
Expand Down
5 changes: 5 additions & 0 deletions apps/web/locales/vi/ws-members.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"description": "Quản lý thành viên trong không gian làm việc.",
"invite_member": "Mời thành viên",
"enter_email_or_username": "Nhập email hoặc tên người dùng",
"member_since": "Đã tham gia",
"pending_invitations": "Lời mời đang chờ",
"invited": "Đã mời",
Expand All @@ -9,11 +10,15 @@
"remove_member": "Xóa thành viên",
"member_removed": "Thành viên đã bị xóa",
"revoke_invitation": "Thu hồi lời mời",
"invitation_sent": "Lời mời đã được gửi",
"invitation_revoked": "Lời mời đã bị thu hồi",
"invitation_to": "Lời mời đến",
"has_been_sent": "đã được gửi",
"has_been_revoked": "đã bị thu hồi",
"has_been_removed": "đã bị xóa khỏi không gian làm việc này",
"error": "Lỗi",
"invitation_error": "Đã xảy ra lỗi khi gửi lời mời",
"invitation_error_already_exist": "Người dùng đã là thành viên hoặc lời mời đã được gửi",
"revoke_error": "Đã xảy ra lỗi khi thu hồi lời mời",
"remove_error": "Đã xảy ra lỗi khi xóa thành viên",
"member-settings": "Cài đặt thành viên",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"@types/jest": "^29.5.2",
"@types/js-cookie": "^3.0.3",
"@types/lodash": "^4.14.195",
"@types/node": "^20.4.0",
"@types/node": "^20.4.1",
"@types/react": "^18.2.14",
"@types/react-beautiful-dnd": "^13.1.4",
"@types/react-dom": "^18.2.6",
Expand Down
55 changes: 21 additions & 34 deletions apps/web/src/components/forms/SelectUserForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
isIncompleteEmail,
suggestEmails,
} from '../../utils/email-helper';
import useTranslation from 'next-translate/useTranslation';

interface SelectUserFormProps {
wsId: string;
Expand All @@ -18,6 +19,8 @@ interface SelectUserFormProps {
type UserWithValue = User & { value: string };

const SelectUserForm = ({ wsId }: SelectUserFormProps) => {
const { t } = useTranslation('ws-members');

const [value, setValue] = useState('');
const [debounced] = useDebouncedValue(value, 300);

Expand Down Expand Up @@ -111,19 +114,18 @@ const SelectUserForm = ({ wsId }: SelectUserFormProps) => {
closeAllModals();

showNotification({
title: 'Invitation sent',
message: `Invitation to ${
title: t('invitation_sent'),
message: `${t('invitation_to')} ${
(selectedUser?.handle && `@${selectedUser?.handle}`) ||
selectedUser?.display_name ||
value
} has been sent`,
} ${t('has_been_sent')}`,
color: 'teal',
});
} else {
const res = await response.json();
showNotification({
title: 'Could not invite user',
message: res?.error?.message || 'Something went wrong',
title: t('invitation_error'),
message: t('invitation_error_already_exist'),
color: 'red',
});
}
Expand All @@ -137,7 +139,7 @@ const SelectUserForm = ({ wsId }: SelectUserFormProps) => {
<Autocomplete
value={value}
onChange={setValue}
placeholder="Enter an handle or email"
placeholder={t('enter_email_or_username')}
itemComponent={AutoCompleteItem}
data={suggestions}
onItemSubmit={(item) => {
Expand All @@ -149,7 +151,7 @@ const SelectUserForm = ({ wsId }: SelectUserFormProps) => {
withinPortal
/>
) : (
<Group className="rounded-lg border border-zinc-800/80 bg-blue-300/10 p-4">
<Group className="rounded border border-zinc-800/80 bg-blue-300/10 px-4 py-2 text-blue-300 dark:border-blue-300/10">
{selectedUser?.id === value ? (
<Text>{value}</Text>
) : (
Expand All @@ -172,32 +174,17 @@ const SelectUserForm = ({ wsId }: SelectUserFormProps) => {
</Group>
)}

<div>
{isEmail(value) ? (
<Button
fullWidth
variant="subtle"
color="teal"
onClick={handleInvite}
loading={inviting}
mt="md"
>
{inviting ? 'Inviting...' : 'Invite'}
</Button>
) : (
<Button
fullWidth
variant="subtle"
color="teal"
onClick={handleInvite}
loading={inviting}
mt="md"
disabled={!selectedUser}
>
{inviting ? 'Inviting...' : 'Invite'}
</Button>
)}
</div>
<Button
fullWidth
variant="light"
className="bg-blue-300/10 hover:bg-blue-300/20"
onClick={handleInvite}
loading={inviting}
disabled={!selectedUser && !isEmail(value)}
mt="xs"
>
{t('invite_member')}
</Button>
</>
);
};
Expand Down
34 changes: 15 additions & 19 deletions apps/web/src/components/notifications/WorkspaceInviteSnippet.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import moment from 'moment';
import { Workspace } from '../../types/primitives/Workspace';
import { Divider } from '@mantine/core';
import useTranslation from 'next-translate/useTranslation';
import { mutate } from 'swr';
import { showNotification } from '@mantine/notifications';
import 'moment/locale/vi';

interface Props {
ws: Workspace;
gray?: boolean;
transparent?: boolean;
}

const WorkspaceInviteSnippet = ({ ws, gray = false }: Props) => {
const WorkspaceInviteSnippet = ({ ws, transparent = true }: Props) => {
const { t, lang } = useTranslation('invite');

const creationDate = moment(ws?.created_at).locale(lang).fromNow();
Expand Down Expand Up @@ -78,36 +77,33 @@ const WorkspaceInviteSnippet = ({ ws, gray = false }: Props) => {

return (
<div
className={`rounded-lg border p-4 md:p-8 ${
gray
? 'border-zinc-300/10 bg-zinc-900'
: 'border-blue-300/20 bg-blue-300/10'
className={`rounded-lg border p-4 ${
transparent
? 'border-zinc-300/10 bg-zinc-300/5'
: 'border-zinc-300/10 bg-zinc-900'
}`}
>
{ws?.created_at ? (
<>
<div className="w-fit rounded border border-purple-300/10 bg-purple-300/10 px-4 py-0.5 text-purple-300">
{creationDate}
</div>
<Divider className="my-2 border-blue-300/20" />
</>
) : null}

<div className="cursor-default font-semibold transition duration-150">
<span className="text-zinc-300/60">{invitedTo} </span>
<span className="text-zinc-200">{ws?.name || `Unnamed Workspace`}</span>
{ws?.created_at ? (
<span className="font-normal text-zinc-300/60">
{' '}
• {creationDate}
</span>
) : null}
</div>

<div className="mt-4 grid gap-2 md:grid-cols-2">
<div className="mt-2 grid gap-2 md:grid-cols-2">
<div
className="flex cursor-pointer items-center justify-center rounded border border-zinc-300/10 bg-zinc-300/5 p-2 font-semibold text-zinc-300 transition duration-300 hover:border-red-300/10 hover:bg-red-300/10 hover:text-red-300"
className="flex cursor-pointer items-center justify-center rounded border border-zinc-300/10 bg-zinc-300/5 p-1 font-semibold text-zinc-300 transition duration-300 hover:border-red-300/10 hover:bg-red-300/10 hover:text-red-300"
onClick={() => declineInvite(ws)}
>
{declineInviteLabel}
</div>

<div
className="flex flex-1 cursor-pointer items-center justify-center rounded border border-zinc-300/10 bg-zinc-300/5 p-2 font-semibold text-zinc-300 transition duration-300 hover:border-green-300/10 hover:bg-green-300/10 hover:text-green-300"
className="flex flex-1 cursor-pointer items-center justify-center rounded border border-zinc-300/10 bg-zinc-300/5 p-1 font-semibold text-zinc-300 transition duration-300 hover:border-green-300/10 hover:bg-green-300/10 hover:text-green-300"
onClick={() => acceptInvite(ws)}
>
{acceptInviteLabel}
Expand Down
25 changes: 23 additions & 2 deletions apps/web/src/components/onboarding/OnboardingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useUser } from '../../hooks/useUser';
import useTranslation from 'next-translate/useTranslation';
import LanguageSelector from '../selectors/LanguageSelector';
import { mutate } from 'swr';
import { useSessionContext } from '@supabase/auth-helpers-react';

interface Props {
forceLoading?: boolean;
Expand Down Expand Up @@ -80,6 +81,7 @@ const OnboardingForm = ({ forceLoading = false }: Props) => {
};

const { t } = useTranslation('onboarding');
const { supabaseClient } = useSessionContext();

const displayNameLabel = t('display-name');
const usernameLabel = t('username');
Expand All @@ -94,10 +96,16 @@ const OnboardingForm = ({ forceLoading = false }: Props) => {

const currentlyLoggedIn = t('currently-logged-in');
const noInvites = t('no-invites');
const logoutLabel = t('common:logout');

const handleLogout = async () => {
await supabaseClient.auth.signOut();
router.push('/');
};

return (
<>
<div className="absolute inset-0 mx-4 my-32 flex items-start justify-center md:mx-4 md:items-center lg:mx-32">
<div className="absolute inset-0 mx-4 flex items-center justify-center md:mx-4 lg:mx-32">
<div className="flex max-h-full w-full max-w-2xl flex-col items-center gap-4 rounded-xl bg-zinc-700/50 p-4 backdrop-blur-2xl md:p-8">
{forceLoading ||
!user ||
Expand Down Expand Up @@ -202,7 +210,20 @@ const OnboardingForm = ({ forceLoading = false }: Props) => {
)}

<Divider className="w-full border-zinc-300/20" />
<LanguageSelector transparent fullWidth />
<div className="grid w-full gap-2">
<LanguageSelector transparent fullWidth />
<Button
className="w-full border border-red-300/10 bg-red-300/10 text-red-300 hover:bg-red-300/20"
variant="light"
color="red"
onClick={(e) => {
e.preventDefault();
handleLogout();
}}
>
{logoutLabel}
</Button>
</div>
</>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/[wsId]/notifications/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const NotificationsPage = () => {
) : (workspaceInvites?.length || 0) > 0 ? (
<div className="mb-16 grid gap-4 xl:grid-cols-2">
{workspaceInvites?.map((ws) => (
<WorkspaceInviteSnippet key={ws.id} ws={ws} gray />
<WorkspaceInviteSnippet key={ws.id} ws={ws} transparent={false} />
))}
</div>
) : (
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/logout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const LogOutPage = () => {

<div className="grid w-full gap-2 text-center">
<Button
className="bg-red-300/10 text-red-300 hover:bg-red-300/20"
className="bg-red-300/10 text-red-300 border border-red-300/10 hover:bg-red-300/20"
variant="light"
color="red"
onClick={(e) => {
Expand Down
Loading