- {mode
- ? mode === EAuthModes.SIGN_UP
- ? "By creating an account"
- : "By signing in"
- : "By clicking the above button"}
- , you agree to our{" \n"}
+ {isSignUp ? "By creating an account" : "By signing in"}, you agree to our{" \n"}
Terms of Service
{" "}
diff --git a/space/components/accounts/user-logged-in.tsx b/space/components/account/user-logged-in.tsx
similarity index 92%
rename from space/components/accounts/user-logged-in.tsx
rename to space/components/account/user-logged-in.tsx
index afd3016a6..d0f177038 100644
--- a/space/components/accounts/user-logged-in.tsx
+++ b/space/components/account/user-logged-in.tsx
@@ -4,8 +4,8 @@ import Image from "next/image";
// hooks
import { useUser } from "@/hooks/store";
// assets
-import PlaneLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
-import UserLoggedInImage from "public/user-logged-in.svg";
+import PlaneLogo from "@/public/plane-logos/black-horizontal-with-blue-logo.svg";
+import UserLoggedInImage from "@/public/user-logged-in.svg";
export const UserLoggedIn = () => {
const { data: user } = useUser();
diff --git a/space/components/accounts/auth-forms/email.tsx b/space/components/accounts/auth-forms/email.tsx
deleted file mode 100644
index 8f40b74d5..000000000
--- a/space/components/accounts/auth-forms/email.tsx
+++ /dev/null
@@ -1,94 +0,0 @@
-"use client";
-
-import React from "react";
-import { Controller, useForm } from "react-hook-form";
-// icons
-import { XCircle, CircleAlert } from "lucide-react";
-// ui
-import { Button, Input, Spinner } from "@plane/ui";
-// helpers
-import { checkEmailValidity } from "@/helpers/string.helper";
-// types
-import { IEmailCheckData } from "@/types/auth";
-
-type Props = {
- onSubmit: (data: IEmailCheckData) => Promise;
-};
-
-type TEmailFormValues = {
- email: string;
-};
-
-export const EmailForm: React.FC = (props) => {
- const { onSubmit } = props;
-
- const {
- control,
- formState: { errors, isSubmitting, isValid },
- handleSubmit,
- } = useForm({
- defaultValues: {
- email: "",
- },
- mode: "onChange",
- reValidateMode: "onChange",
- });
-
- const handleFormSubmit = async (data: TEmailFormValues) => {
- const payload: IEmailCheckData = {
- email: data.email,
- };
- onSubmit(payload);
- };
-
- return (
-
- );
-};
diff --git a/space/components/accounts/auth-forms/forgot-password-popover.tsx b/space/components/accounts/auth-forms/forgot-password-popover.tsx
deleted file mode 100644
index 8e0f2064c..000000000
--- a/space/components/accounts/auth-forms/forgot-password-popover.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client";
-import { Fragment, useState } from "react";
-import { usePopper } from "react-popper";
-import { X } from "lucide-react";
-import { Popover } from "@headlessui/react";
-
-export const ForgotPasswordPopover = () => {
- // popper-js refs
- const [referenceElement, setReferenceElement] = useState(null);
- const [popperElement, setPopperElement] = useState(null);
- // popper-js init
- const { styles, attributes } = usePopper(referenceElement, popperElement, {
- placement: "right-start",
- modifiers: [
- {
- name: "preventOverflow",
- options: {
- padding: 12,
- },
- },
- ],
- });
-
- return (
-
-
-
-
-
- {({ close }) => (
-
-
🤥
-
- We see that your god hasn{"'"}t enabled SMTP, we will not be able to send a password reset link
-
-
-
- )}
-
-
- );
-};
diff --git a/space/components/accounts/auth-forms/index.ts b/space/components/accounts/auth-forms/index.ts
deleted file mode 100644
index 68f0e3afd..000000000
--- a/space/components/accounts/auth-forms/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from "./email";
-export * from "./password";
-export * from "./root";
-export * from "./unique-code";
-export * from "./forgot-password-popover";
diff --git a/space/components/accounts/auth-forms/root.tsx b/space/components/accounts/auth-forms/root.tsx
deleted file mode 100644
index e51cac92f..000000000
--- a/space/components/accounts/auth-forms/root.tsx
+++ /dev/null
@@ -1,160 +0,0 @@
-"use client";
-
-import React, { useState } from "react";
-import { observer } from "mobx-react-lite";
-// components
-import { IEmailCheckData } from "@plane/types";
-import { EmailForm, UniqueCodeForm, PasswordForm, OAuthOptions, TermsAndConditions } from "@/components/accounts";
-// hooks
-import { useInstance } from "@/hooks/store";
-import useToast from "@/hooks/use-toast";
-// services
-import { AuthService } from "@/services/auth.service";
-
-export enum EAuthSteps {
- EMAIL = "EMAIL",
- PASSWORD = "PASSWORD",
- UNIQUE_CODE = "UNIQUE_CODE",
-}
-
-export enum EAuthModes {
- SIGN_IN = "SIGN_IN",
- SIGN_UP = "SIGN_UP",
-}
-
-type TTitle = {
- header: string;
- subHeader: string;
-};
-
-type THeaderSubheader = {
- [mode in EAuthModes]: TTitle;
-};
-
-const titles: THeaderSubheader = {
- [EAuthModes.SIGN_IN]: {
- header: "Sign in to upvote or comment",
- subHeader: "Contribute in nudging the features you want to get built.",
- },
- [EAuthModes.SIGN_UP]: {
- header: "Comment or react to issues",
- subHeader: "Use plane to add your valuable inputs to features.",
- },
-};
-
-const getHeaderSubHeader = (mode: EAuthModes | null): TTitle => {
- if (mode) {
- return titles[mode];
- }
-
- return {
- header: "Comment or react to issues",
- subHeader: "Use plane to add your valuable inputs to features.",
- };
-};
-
-const authService = new AuthService();
-
-export const AuthRoot = observer(() => {
- const { setToastAlert } = useToast();
- // states
- const [authMode, setAuthMode] = useState(null);
- const [authStep, setAuthStep] = useState(EAuthSteps.EMAIL);
- const [email, setEmail] = useState("");
- // hooks
- const { config: instanceConfig } = useInstance();
- // derived values
- const isSmtpConfigured = instanceConfig?.is_smtp_configured;
- const isMagicLoginEnabled = instanceConfig?.is_magic_login_enabled;
- const isEmailPasswordEnabled = instanceConfig?.is_email_password_enabled;
-
- const { header, subHeader } = getHeaderSubHeader(authMode);
-
- const handelEmailVerification = async (data: IEmailCheckData) => {
- // update the global email state
- setEmail(data.email);
-
- await authService
- .emailCheck(data)
- .then((res) => {
- // Set authentication mode based on user existing status.
- if (res.existing) {
- setAuthMode(EAuthModes.SIGN_IN);
- } else {
- setAuthMode(EAuthModes.SIGN_UP);
- }
-
- // If user exists and password is already setup by the user, move to password sign in.
- if (res.existing && !res.is_password_autoset) {
- setAuthStep(EAuthSteps.PASSWORD);
- } else {
- // Else if SMTP is configured, move to unique code sign-in/ sign-up.
- if (isSmtpConfigured && isMagicLoginEnabled) {
- setAuthStep(EAuthSteps.UNIQUE_CODE);
- } else if (isEmailPasswordEnabled) {
- // Else show error message if SMTP is not configured and password is not set.
- if (res.existing) {
- setAuthMode(null);
- setToastAlert({
- type: "error",
- title: "Error!",
- message: "Unable to process request please contact Administrator to reset password",
- });
- } else {
- // If SMTP is not configured and user is new, move to password sign-up.
- setAuthStep(EAuthSteps.PASSWORD);
- }
- }
- }
- })
- .catch((err) =>
- setToastAlert({
- type: "error",
- title: "Error!",
- message: err?.error ?? "Something went wrong. Please try again.",
- })
- );
- };
-
- const isOAuthEnabled = instanceConfig && (instanceConfig?.is_google_enabled || instanceConfig?.is_github_enabled);
-
- return (
-
-
-
{header}
-
{subHeader}
-
- {authStep === EAuthSteps.EMAIL &&
}
- {authMode && (
- <>
- {authStep === EAuthSteps.PASSWORD && (
-
{
- setEmail("");
- setAuthMode(null);
- setAuthStep(EAuthSteps.EMAIL);
- }}
- handleStepChange={(step) => setAuthStep(step)}
- />
- )}
- {authStep === EAuthSteps.UNIQUE_CODE && (
- {
- setEmail("");
- setAuthMode(null);
- setAuthStep(EAuthSteps.EMAIL);
- }}
- submitButtonText="Continue"
- />
- )}
- >
- )}
- {isOAuthEnabled !== undefined && }
-
-
- );
-});
diff --git a/space/components/accounts/onboarding-form.tsx b/space/components/accounts/onboarding-form.tsx
deleted file mode 100644
index 50e5f0f0d..000000000
--- a/space/components/accounts/onboarding-form.tsx
+++ /dev/null
@@ -1,216 +0,0 @@
-"use client";
-
-import React, { useMemo, useState } from "react";
-import { observer } from "mobx-react-lite";
-import { Controller, useForm } from "react-hook-form";
-// types
-import { IUser } from "@plane/types";
-// ui
-import { Button, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui";
-// components
-import { UserImageUploadModal } from "@/components/accounts";
-// hooks
-import { useUser } from "@/hooks/store";
-// services
-import fileService from "@/services/file.service";
-
-type TProfileSetupFormValues = {
- first_name: string;
- last_name: string;
- avatar?: string | null;
-};
-
-const defaultValues: Partial = {
- first_name: "",
- last_name: "",
- avatar: "",
-};
-
-type Props = {
- user?: IUser;
- finishOnboarding: () => Promise;
-};
-
-export const OnBoardingForm: React.FC = observer((props) => {
- const { user, finishOnboarding } = props;
- // states
- const [isRemoving, setIsRemoving] = useState(false);
- const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false);
- // store hooks
- const { updateCurrentUser } = useUser();
- // form info
- const {
- getValues,
- handleSubmit,
- control,
- watch,
- setValue,
- formState: { errors, isSubmitting, isValid },
- } = useForm({
- defaultValues: {
- ...defaultValues,
- first_name: user?.first_name,
- last_name: user?.last_name,
- avatar: user?.avatar,
- },
- mode: "onChange",
- });
-
- const onSubmit = async (formData: TProfileSetupFormValues) => {
- if (!user) return;
-
- const userDetailsPayload: Partial = {
- first_name: formData.first_name,
- last_name: formData.last_name,
- avatar: formData.avatar,
- };
-
- try {
- await updateCurrentUser(userDetailsPayload).then(() => {
- setToast({
- type: TOAST_TYPE.SUCCESS,
- title: "Success",
- message: "Profile setup completed!",
- });
- finishOnboarding();
- });
- } catch {
- setToast({
- type: TOAST_TYPE.ERROR,
- title: "Error",
- message: "Profile setup failed. Please try again!",
- });
- }
- };
-
- const handleDelete = (url: string | null | undefined) => {
- if (!url) return;
-
- setIsRemoving(true);
- fileService.deleteUserFile(url).finally(() => {
- setValue("avatar", "");
- setIsRemoving(false);
- });
- };
-
- const isButtonDisabled = useMemo(() => (isValid && !isSubmitting ? false : true), [isSubmitting, isValid]);
-
- return (
-
- );
-});
diff --git a/space/components/accounts/user-image-upload-modal.tsx b/space/components/accounts/user-image-upload-modal.tsx
deleted file mode 100644
index 802a6af62..000000000
--- a/space/components/accounts/user-image-upload-modal.tsx
+++ /dev/null
@@ -1,186 +0,0 @@
-"use client";
-import React, { useState } from "react";
-import { observer } from "mobx-react-lite";
-import { useDropzone } from "react-dropzone";
-import { UserCircle2 } from "lucide-react";
-import { Transition, Dialog } from "@headlessui/react";
-// hooks
-import { Button, TOAST_TYPE, setToast } from "@plane/ui";
-// hooks
-import { useInstance } from "@/hooks/store";
-// services
-import fileService from "@/services/file.service";
-
-type Props = {
- handleDelete?: () => void;
- isOpen: boolean;
- isRemoving: boolean;
- onClose: () => void;
- onSuccess: (url: string) => void;
- value: string | null;
-};
-
-const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
-
-export const UserImageUploadModal: React.FC = observer((props) => {
- const { value, onSuccess, isOpen, onClose, isRemoving, handleDelete } = props;
- // states
- const [image, setImage] = useState(null);
- const [isImageUploading, setIsImageUploading] = useState(false);
- // store hooks
- const { config: instanceConfig } = useInstance();
-
- const onDrop = (acceptedFiles: File[]) => setImage(acceptedFiles[0]);
-
- const { getRootProps, getInputProps, isDragActive, fileRejections } = useDropzone({
- onDrop,
- accept: {
- "image/*": [".png", ".jpg", ".jpeg", ".svg", ".webp"],
- },
- maxSize: (instanceConfig?.file_size_limit as number) ?? MAX_FILE_SIZE,
- multiple: false,
- });
-
- const handleClose = () => {
- setImage(null);
- setIsImageUploading(false);
- onClose();
- };
-
- const handleSubmit = async () => {
- if (!image) return;
-
- setIsImageUploading(true);
-
- const formData = new FormData();
- formData.append("asset", image);
- formData.append("attributes", JSON.stringify({}));
-
- fileService
- .uploadUserFile(formData)
- .then((res) => {
- const imageUrl = res.asset;
-
- onSuccess(imageUrl);
- setImage(null);
-
- if (value) fileService.deleteUserFile(value);
- })
- .catch((err) =>
- setToast({
- type: TOAST_TYPE.ERROR,
- title: "Error!",
- message: err?.error ?? "Something went wrong. Please try again.",
- })
- )
- .finally(() => setIsImageUploading(false));
- };
-
- return (
-
-
-
- );
-});
diff --git a/space/components/issues/board-views/kanban/block.tsx b/space/components/issues/board-views/kanban/block.tsx
index 9b7c87b8d..e34222dd4 100644
--- a/space/components/issues/board-views/kanban/block.tsx
+++ b/space/components/issues/board-views/kanban/block.tsx
@@ -7,6 +7,8 @@ import { useRouter, useSearchParams } from "next/navigation";
import { IssueBlockDueDate } from "@/components/issues/board-views/block-due-date";
import { IssueBlockPriority } from "@/components/issues/board-views/block-priority";
import { IssueBlockState } from "@/components/issues/board-views/block-state";
+// helpers
+import { queryParamGenerator } from "@/helpers/query-param-generator";
// hooks
import { useIssueDetails, useProject } from "@/hooks/store";
// interfaces
@@ -20,22 +22,23 @@ type IssueKanBanBlockProps = {
};
export const IssueKanBanBlock: FC = observer((props) => {
- const { workspaceSlug, projectId, params, issue } = props;
- const { board, priority, states, labels } = params;
- // store
- const { project } = useProject();
- const { setPeekId } = useIssueDetails();
- // router
const router = useRouter();
const searchParams = useSearchParams();
+ // query params
+ const board = searchParams.get("board") || undefined;
+ const state = searchParams.get("state") || undefined;
+ const priority = searchParams.get("priority") || undefined;
+ const labels = searchParams.get("labels") || undefined;
+ // props
+ const { workspaceSlug, projectId, issue } = props;
+ // hooks
+ const { project } = useProject();
+ const { setPeekId } = useIssueDetails();
const handleBlockClick = () => {
setPeekId(issue.id);
- const params: any = { board: board, peekId: issue.id };
- if (states && states.length > 0) params.states = states;
- if (priority && priority.length > 0) params.priority = priority;
- if (labels && labels.length > 0) params.labels = labels;
- router.push(`/${workspaceSlug}/${projectId}?${searchParams}`);
+ const { queryParam } = queryParamGenerator({ board, peekId: issue.id, priority, state, labels });
+ router.push(`/${workspaceSlug}/${projectId}?${queryParam}`);
};
return (
diff --git a/space/components/issues/board-views/list/block.tsx b/space/components/issues/board-views/list/block.tsx
index 5eaa31721..6b6231fcf 100644
--- a/space/components/issues/board-views/list/block.tsx
+++ b/space/components/issues/board-views/list/block.tsx
@@ -7,7 +7,9 @@ import { IssueBlockDueDate } from "@/components/issues/board-views/block-due-dat
import { IssueBlockLabels } from "@/components/issues/board-views/block-labels";
import { IssueBlockPriority } from "@/components/issues/board-views/block-priority";
import { IssueBlockState } from "@/components/issues/board-views/block-state";
-// mobx hook
+// helpers
+import { queryParamGenerator } from "@/helpers/query-param-generator";
+// hook
import { useIssueDetails, useProject } from "@/hooks/store";
// interfaces
import { IIssue } from "@/types/issue";
@@ -35,12 +37,9 @@ export const IssueListBlock: FC = observer((props) => {
const handleBlockClick = () => {
setPeekId(issue.id);
- let queryParams: any = { board: board, peekId: issue.id };
- if (priority && priority.length > 0) queryParams = { ...queryParams, priority: priority };
- if (state && state.length > 0) queryParams = { ...queryParams, state: state };
- if (labels && labels.length > 0) queryParams = { ...queryParams, labels: labels };
- queryParams = new URLSearchParams(queryParams).toString();
- router.push(`/${workspaceSlug}/${projectId}?${queryParams}`);
+
+ const { queryParam } = queryParamGenerator({ board, peekId: issue.id, priority, state, labels });
+ router.push(`/${workspaceSlug}/${projectId}?${queryParam}`);
};
return (
diff --git a/space/components/issues/filters/root.tsx b/space/components/issues/filters/root.tsx
index 08af9c4b8..de972ea8a 100644
--- a/space/components/issues/filters/root.tsx
+++ b/space/components/issues/filters/root.tsx
@@ -4,15 +4,17 @@ import { FC, useCallback } from "react";
import cloneDeep from "lodash/cloneDeep";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/navigation";
+// components
+import { FiltersDropdown } from "@/components/issues/filters/helpers/dropdown";
+import { FilterSelection } from "@/components/issues/filters/selection";
// constants
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue";
+// helpers
+import { queryParamGenerator } from "@/helpers/query-param-generator";
// hooks
import { useIssue, useIssueFilter } from "@/hooks/store";
// types
import { TIssueQueryFilters } from "@/types/issue";
-// components
-import { FiltersDropdown } from "./helpers/dropdown";
-import { FilterSelection } from "./selection";
type IssueFiltersDropdownProps = {
workspaceSlug: string;
@@ -34,13 +36,8 @@ export const IssueFiltersDropdown: FC = observer((pro
const priority = key === "priority" ? value : issueFilters?.filters?.priority ?? [];
const labels = key === "labels" ? value : issueFilters?.filters?.labels ?? [];
- let params: any = { board: activeLayout || "list" };
- if (priority.length > 0) params = { ...params, priority: priority.join(",") };
- if (state.length > 0) params = { ...params, state: state.join(",") };
- if (labels.length > 0) params = { ...params, labels: labels.join(",") };
- params = new URLSearchParams(params).toString();
-
- router.push(`/${workspaceSlug}/${projectId}?${params}`);
+ const { queryParam } = queryParamGenerator({ board: activeLayout, priority, state, labels });
+ router.push(`/${workspaceSlug}/${projectId}?${queryParam}`);
},
[workspaceSlug, projectId, activeLayout, issueFilters, router]
);
diff --git a/space/components/issues/navbar/controls.tsx b/space/components/issues/navbar/controls.tsx
index b996a54cc..a0d8bbbb4 100644
--- a/space/components/issues/navbar/controls.tsx
+++ b/space/components/issues/navbar/controls.tsx
@@ -10,6 +10,8 @@ import { Avatar, Button } from "@plane/ui";
import { IssueFiltersDropdown } from "@/components/issues/filters";
import { NavbarIssueBoardView } from "@/components/issues/navbar/issue-board-view";
import { NavbarTheme } from "@/components/issues/navbar/theme";
+// helpers
+import { queryParamGenerator } from "@/helpers/query-param-generator";
// hooks
import { useProject, useUser, useIssueFilter, useIssueDetails } from "@/hooks/store";
// types
@@ -63,30 +65,19 @@ export const NavbarControls: FC = observer((props) => {
if (currentBoard) {
if (activeLayout === undefined || activeLayout !== currentBoard) {
- let queryParams: any = { board: currentBoard };
- const params: any = { display_filters: { layout: currentBoard }, filters: {} };
-
- if (peekId && peekId.length > 0) {
- queryParams = { ...queryParams, peekId: peekId };
- setPeekId(peekId);
- }
- if (priority && priority.length > 0) {
- queryParams = { ...queryParams, priority: priority };
- params.filters = { ...params.filters, priority: priority.split(",") };
- }
- if (state && state.length > 0) {
- queryParams = { ...queryParams, state: state };
- params.filters = { ...params.filters, state: state.split(",") };
- }
- if (labels && labels.length > 0) {
- queryParams = { ...queryParams, labels: labels };
- params.filters = { ...params.filters, labels: labels.split(",") };
- }
+ const { query, queryParam } = queryParamGenerator({ board: currentBoard, peekId, priority, state, labels });
+ const params: any = {
+ display_filters: { layout: (query?.board as string[])[0] },
+ filters: {
+ priority: query?.priority ?? undefined,
+ state: query?.state ?? undefined,
+ labels: query?.labels ?? undefined,
+ },
+ };
if (!isIssueFiltersUpdated(params)) {
initIssueFilters(projectId, params);
- queryParams = new URLSearchParams(queryParams).toString();
- router.push(`/${workspaceSlug}/${projectId}?${queryParams}`);
+ router.push(`/${workspaceSlug}/${projectId}?${queryParam}`);
}
}
}
diff --git a/space/components/issues/navbar/issue-board-view.tsx b/space/components/issues/navbar/issue-board-view.tsx
index 4581d1800..711229961 100644
--- a/space/components/issues/navbar/issue-board-view.tsx
+++ b/space/components/issues/navbar/issue-board-view.tsx
@@ -5,6 +5,8 @@ import { observer } from "mobx-react-lite";
import { useRouter, useSearchParams } from "next/navigation";
// constants
import { issueLayoutViews } from "@/constants/issue";
+// helpers
+import { queryParamGenerator } from "@/helpers/query-param-generator";
// hooks
import { useIssueFilter } from "@/hooks/store";
// mobx
@@ -33,14 +35,8 @@ export const NavbarIssueBoardView: FC = observer((pro
const handleCurrentBoardView = (boardView: TIssueLayout) => {
updateIssueFilters(projectId, "display_filters", "layout", boardView);
-
- let queryParams: any = { board: boardView };
- if (peekId && peekId.length > 0) queryParams = { ...queryParams, peekId: peekId };
- if (priority && priority.length > 0) queryParams = { ...queryParams, priority: priority };
- if (state && state.length > 0) queryParams = { ...queryParams, state: state };
- if (labels && labels.length > 0) queryParams = { ...queryParams, labels: labels };
- queryParams = new URLSearchParams(queryParams).toString();
- router.push(`/${workspaceSlug}/${projectId}?${queryParams}`);
+ const { queryParam } = queryParamGenerator({ board: boardView, peekId, priority, state, labels });
+ router.push(`/${workspaceSlug}/${projectId}?${queryParam}`);
};
return (
diff --git a/space/components/views/auth.tsx b/space/components/views/auth.tsx
index 0825683c6..15a2bae77 100644
--- a/space/components/views/auth.tsx
+++ b/space/components/views/auth.tsx
@@ -2,14 +2,13 @@
import { observer } from "mobx-react-lite";
import Image from "next/image";
-// ui
import { useTheme } from "next-themes";
// components
-import { AuthRoot } from "@/components/accounts";
+import { AuthRoot } from "@/components/account";
// images
-import PlaneBackgroundPatternDark from "public/auth/background-pattern-dark.svg";
-import PlaneBackgroundPattern from "public/auth/background-pattern.svg";
-import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text-new.png";
+import PlaneBackgroundPatternDark from "@/public/auth/background-pattern-dark.svg";
+import PlaneBackgroundPattern from "@/public/auth/background-pattern.svg";
+import BluePlaneLogoWithoutText from "@/public/plane-logos/blue-without-text-new.png";
export const AuthView = observer(() => {
// hooks
@@ -31,7 +30,7 @@ export const AuthView = observer(() => {
Plane