mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-20 14:01:24 +00:00
chore: add useNavigateTo hook
This commit is contained in:
parent
f78b072bb8
commit
159dfc9446
@ -1,6 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate } from "react-router-dom";
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import { shortcutService } from "../services";
|
import { shortcutService } from "../services";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
import { showCommonDialog } from "./Alert";
|
import { showCommonDialog } from "./Alert";
|
||||||
@ -16,7 +16,7 @@ interface Props {
|
|||||||
const ShortcutActionsDropdown = (props: Props) => {
|
const ShortcutActionsDropdown = (props: Props) => {
|
||||||
const { shortcut } = props;
|
const { shortcut } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigateTo = useNavigateTo();
|
||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
const [showEditDialog, setShowEditDialog] = useState<boolean>(false);
|
const [showEditDialog, setShowEditDialog] = useState<boolean>(false);
|
||||||
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
|
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
|
||||||
@ -34,7 +34,7 @@ const ShortcutActionsDropdown = (props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const gotoAnalytics = () => {
|
const gotoAnalytics = () => {
|
||||||
navigate(`/shortcut/${shortcut.id}#analytics`);
|
navigateTo(`/shortcut/${shortcut.id}#analytics`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { ReactNode, useEffect, useRef } from "react";
|
import { ReactNode, useEffect, useRef, useState } from "react";
|
||||||
import useToggle from "../../hooks/useToggle";
|
|
||||||
import Icon from "../Icon";
|
import Icon from "../Icon";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -11,14 +10,14 @@ interface Props {
|
|||||||
|
|
||||||
const Dropdown: React.FC<Props> = (props: Props) => {
|
const Dropdown: React.FC<Props> = (props: Props) => {
|
||||||
const { trigger, actions, className, actionsClassName } = props;
|
const { trigger, actions, className, actionsClassName } = props;
|
||||||
const [dropdownStatus, toggleDropdownStatus] = useToggle(false);
|
const [dropdownStatus, setDropdownStatus] = useState(false);
|
||||||
const dropdownWrapperRef = useRef<HTMLDivElement>(null);
|
const dropdownWrapperRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dropdownStatus) {
|
if (dropdownStatus) {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
if (!dropdownWrapperRef.current?.contains(event.target as Node)) {
|
if (!dropdownWrapperRef.current?.contains(event.target as Node)) {
|
||||||
toggleDropdownStatus(false);
|
setDropdownStatus(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ const Dropdown: React.FC<Props> = (props: Props) => {
|
|||||||
|
|
||||||
const handleToggleDropdownStatus = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
const handleToggleDropdownStatus = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleDropdownStatus();
|
setDropdownStatus(!dropdownStatus);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
20
frontend/web/src/hooks/useNavigateTo.ts
Normal file
20
frontend/web/src/hooks/useNavigateTo.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { NavigateOptions, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
const useNavigateTo = () => {
|
||||||
|
const navigateTo = useNavigate();
|
||||||
|
|
||||||
|
const navigateToWithViewTransition = (to: string, options?: NavigateOptions) => {
|
||||||
|
const document = window.document as any;
|
||||||
|
if (!document.startViewTransition) {
|
||||||
|
navigateTo(to, options);
|
||||||
|
} else {
|
||||||
|
document.startViewTransition(() => {
|
||||||
|
navigateTo(to, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return navigateToWithViewTransition;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useNavigateTo;
|
@ -1,21 +0,0 @@
|
|||||||
import { useCallback, useState } from "react";
|
|
||||||
|
|
||||||
// Parameter is the boolean, with default "false" value
|
|
||||||
const useToggle = (initialState = false): [boolean, (nextState?: boolean) => void] => {
|
|
||||||
// Initialize the state
|
|
||||||
const [state, setState] = useState(initialState);
|
|
||||||
|
|
||||||
// Define and memorize toggler function in case we pass down the comopnent,
|
|
||||||
// This function change the boolean value to it's opposite value
|
|
||||||
const toggle = useCallback((nextState?: boolean) => {
|
|
||||||
if (nextState !== undefined) {
|
|
||||||
setState(nextState);
|
|
||||||
} else {
|
|
||||||
setState((state) => !state);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return [state, toggle];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useToggle;
|
|
@ -2,13 +2,14 @@ import { useColorScheme } from "@mui/joy";
|
|||||||
import { isEqual } from "lodash-es";
|
import { isEqual } from "lodash-es";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Outlet, useNavigate } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import { UserSetting_ColorTheme } from "@/types/proto/api/v2/user_setting_service";
|
import { UserSetting_ColorTheme } from "@/types/proto/api/v2/user_setting_service";
|
||||||
import Header from "../components/Header";
|
import Header from "../components/Header";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
|
|
||||||
const Root: React.FC = () => {
|
const Root: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigateTo = useNavigateTo();
|
||||||
const { setMode } = useColorScheme();
|
const { setMode } = useColorScheme();
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
@ -18,7 +19,7 @@ const Root: React.FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
navigate("/auth", {
|
navigateTo("/auth", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -69,7 +69,7 @@ const Home: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<FilterView />
|
<FilterView />
|
||||||
{loadingState.isLoading ? (
|
{loadingState.isLoading ? (
|
||||||
<div className="py-12 w-full flex flex-row justify-center items-center opacity-80">
|
<div className="py-12 w-full flex flex-row justify-center items-center opacity-80 dark:text-gray-500">
|
||||||
<Icon.Loader className="mr-2 w-5 h-auto animate-spin" />
|
<Icon.Loader className="mr-2 w-5 h-auto animate-spin" />
|
||||||
loading
|
loading
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,8 @@ import copy from "copy-to-clipboard";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useLoaderData, useNavigate } from "react-router-dom";
|
import { useLoaderData } from "react-router-dom";
|
||||||
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import { showCommonDialog } from "../components/Alert";
|
import { showCommonDialog } from "../components/Alert";
|
||||||
import AnalyticsView from "../components/AnalyticsView";
|
import AnalyticsView from "../components/AnalyticsView";
|
||||||
import CreateShortcutDialog from "../components/CreateShortcutDialog";
|
import CreateShortcutDialog from "../components/CreateShortcutDialog";
|
||||||
@ -23,7 +24,7 @@ interface State {
|
|||||||
|
|
||||||
const ShortcutDetail = () => {
|
const ShortcutDetail = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigateTo = useNavigateTo();
|
||||||
const shortcutId = (useLoaderData() as Shortcut).id;
|
const shortcutId = (useLoaderData() as Shortcut).id;
|
||||||
const shortcut = shortcutService.getShortcutById(shortcutId) as Shortcut;
|
const shortcut = shortcutService.getShortcutById(shortcutId) as Shortcut;
|
||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
@ -56,7 +57,7 @@ const ShortcutDetail = () => {
|
|||||||
style: "danger",
|
style: "danger",
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
await shortcutService.deleteShortcutById(shortcut.id);
|
await shortcutService.deleteShortcutById(shortcut.id);
|
||||||
navigate("/", {
|
navigateTo("/", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,8 @@ import { Button, Input } from "@mui/joy";
|
|||||||
import React, { FormEvent, useEffect, useState } from "react";
|
import React, { FormEvent, useEffect, useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
@ -10,7 +11,7 @@ import useUserStore from "../stores/v1/user";
|
|||||||
|
|
||||||
const SignIn: React.FC = () => {
|
const SignIn: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigateTo = useNavigateTo();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const workspaceStore = useWorkspaceStore();
|
const workspaceStore = useWorkspaceStore();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@ -20,7 +21,7 @@ const SignIn: React.FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userStore.getCurrentUser()) {
|
if (userStore.getCurrentUser()) {
|
||||||
return navigate("/", {
|
return navigateTo("/", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -52,7 +53,7 @@ const SignIn: React.FC = () => {
|
|||||||
await api.signin(email, password);
|
await api.signin(email, password);
|
||||||
const user = await userStore.fetchCurrentUser();
|
const user = await userStore.fetchCurrentUser();
|
||||||
if (user) {
|
if (user) {
|
||||||
navigate("/", {
|
navigateTo("/", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,7 +2,8 @@ import { Button, Input } from "@mui/joy";
|
|||||||
import React, { FormEvent, useEffect, useState } from "react";
|
import React, { FormEvent, useEffect, useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
@ -10,7 +11,7 @@ import useUserStore from "../stores/v1/user";
|
|||||||
|
|
||||||
const SignUp: React.FC = () => {
|
const SignUp: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigateTo = useNavigateTo();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const workspaceStore = useWorkspaceStore();
|
const workspaceStore = useWorkspaceStore();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@ -21,13 +22,13 @@ const SignUp: React.FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userStore.getCurrentUser()) {
|
if (userStore.getCurrentUser()) {
|
||||||
return navigate("/", {
|
return navigateTo("/", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!workspaceStore.setting.enableSignup) {
|
if (!workspaceStore.setting.enableSignup) {
|
||||||
return navigate("/auth", {
|
return navigateTo("/auth", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ const SignUp: React.FC = () => {
|
|||||||
await api.signup(email, nickname, password);
|
await api.signup(email, nickname, password);
|
||||||
const user = await userStore.fetchCurrentUser();
|
const user = await userStore.fetchCurrentUser();
|
||||||
if (user) {
|
if (user) {
|
||||||
navigate("/", {
|
navigateTo("/", {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user