[common/features, apps/cs] feat: 게시물 퍼가기(url 복사) 기능 추가
This commit is contained in:
@@ -29,9 +29,11 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"js-cookie": "^3.0.5",
|
||||
"next": "15.3.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"sonner": "^2.0.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tus-js-client": "^4.3.1",
|
||||
"zod": "^3.24.2",
|
||||
|
||||
@@ -5,10 +5,11 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import { ConfirmProvider } from "@frontend-opensource/use-react-hooks";
|
||||
import { AuthWrapper } from "@/entities/auth";
|
||||
import { MenuWrapper } from "@/entities/menu";
|
||||
import { StoreProvider, PromptProvider } from "@/shared/providers";
|
||||
import { Toaster } from "@/shared/ui/sonner";
|
||||
import { AlertDialog } from "@/shared/ui/alert-dialog";
|
||||
import { PromptDialog } from "@/shared/ui/prompt-dialog";
|
||||
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
|
||||
import { StoreProvider, PromptProvider } from "@/shared/providers";
|
||||
|
||||
const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
const queryClient = new QueryClient();
|
||||
@@ -22,6 +23,7 @@ const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
<AlertDialog />
|
||||
<PromptDialog />
|
||||
<ConfirmDialog />
|
||||
<Toaster position="top-center" />
|
||||
</AuthWrapper>
|
||||
</ConfirmProvider>
|
||||
</PromptProvider>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useTheme } from "next-themes";
|
||||
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme();
|
||||
|
||||
return (
|
||||
<Sonner
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { Toaster };
|
||||
@@ -1,5 +1,7 @@
|
||||
import { toast } from "sonner";
|
||||
import { useEffect } from "react";
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { useClipboard, useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { Button } from "@common/components";
|
||||
import { AuthorityButton } from "@/entities/menu-authority";
|
||||
import { useMenuStore, useUserStore } from "@/shared/lib";
|
||||
@@ -13,6 +15,7 @@ type PostActionProps = {
|
||||
function PostAction({ registerId, children, handleDelete }: PostActionProps) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const { copyText, copied } = useClipboard();
|
||||
const { confirm } = useConfirm();
|
||||
const bbsInfo = useMenuStore((state) => state.bbsInfo);
|
||||
const userInfo = useUserStore((state) => state.userInfo);
|
||||
@@ -37,10 +40,22 @@ function PostAction({ registerId, children, handleDelete }: PostActionProps) {
|
||||
return true;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (copied) toast.success("URL이 클립보드에 복사되었습니다.");
|
||||
}, [copied]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<div className="flex justify-center gap-4 pb-12 pt-10">
|
||||
<Button
|
||||
size="lg"
|
||||
color="emerald"
|
||||
type="button"
|
||||
onClick={() => copyText(window.location.href)}
|
||||
>
|
||||
퍼가기
|
||||
</Button>
|
||||
<Button
|
||||
size="lg"
|
||||
color="white"
|
||||
|
||||
@@ -35,9 +35,11 @@
|
||||
"lucide-react": "^0.474.0",
|
||||
"next": "15.3.0",
|
||||
"next-qrcode": "^2.5.1",
|
||||
"next-themes": "^0.4.6",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"sonner": "^2.0.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tus-js-client": "^4.3.1",
|
||||
"zod": "^3.24.2",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import { ConfirmProvider } from "@frontend-opensource/use-react-hooks";
|
||||
import { AuthWrapper } from "@/entities/auth";
|
||||
import { MenuWrapper } from "@/entities/menu";
|
||||
import { Toaster } from "@/shared/ui/sonner";
|
||||
import { AlertDialog } from "@/shared/ui/alert-dialog";
|
||||
import { PromptDialog } from "@/shared/ui/prompt-dialog";
|
||||
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
|
||||
@@ -33,6 +34,7 @@ const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
<PromptDialog />
|
||||
<ConfirmDialog />
|
||||
<SelectPromptDialog />
|
||||
<Toaster position="top-center" />
|
||||
</AuthWrapper>
|
||||
</ConfirmProvider>
|
||||
</PromptProvider>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useTheme } from "next-themes";
|
||||
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme();
|
||||
|
||||
return (
|
||||
<Sonner
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { Toaster };
|
||||
@@ -1,6 +1,10 @@
|
||||
import { toast } from "sonner";
|
||||
import { useEffect } from "react";
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
import { useClipboard } from "@frontend-opensource/use-react-hooks";
|
||||
import { Button } from "@common/components";
|
||||
import { deleteReasonMessages } from "@/entities/post";
|
||||
import { AuthorityButton } from "@/entities/menu-authority";
|
||||
import { useMenuStore, useSelectPrompt, useUserStore } from "@/shared/lib";
|
||||
|
||||
type PostActionProps = {
|
||||
@@ -17,6 +21,7 @@ const selectData = Object.entries(deleteReasonMessages).map(
|
||||
function PostAction({ children, handleDelete }: PostActionProps) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const { copyText, copied } = useClipboard();
|
||||
const { prompt } = useSelectPrompt(selectData);
|
||||
const bbsInfo = useMenuStore((state) => state.bbsInfo);
|
||||
const userInfo = useUserStore((state) => state.userInfo);
|
||||
@@ -39,10 +44,22 @@ function PostAction({ children, handleDelete }: PostActionProps) {
|
||||
return true;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (copied) toast.success("URL이 클립보드에 복사되었습니다.");
|
||||
}, [copied]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<div className="flex justify-center gap-4 pb-12 pt-10">
|
||||
<Button
|
||||
size="lg"
|
||||
color="emerald"
|
||||
type="button"
|
||||
onClick={() => copyText(window.location.href)}
|
||||
>
|
||||
퍼가기
|
||||
</Button>
|
||||
<Button
|
||||
size="lg"
|
||||
color="white"
|
||||
@@ -51,15 +68,17 @@ function PostAction({ children, handleDelete }: PostActionProps) {
|
||||
>
|
||||
목록
|
||||
</Button>
|
||||
<Button
|
||||
<AuthorityButton
|
||||
authority="mdfcnAuthrtYn"
|
||||
size="lg"
|
||||
type="button"
|
||||
onClick={() => router.push(`${pathname}/modify`)}
|
||||
>
|
||||
수정
|
||||
</Button>
|
||||
</AuthorityButton>
|
||||
{bbsInfo?.ansUseYn === "Y" && (
|
||||
<Button
|
||||
<AuthorityButton
|
||||
authority="regAuthrtYn"
|
||||
size="lg"
|
||||
type="button"
|
||||
color="gray"
|
||||
@@ -67,11 +86,17 @@ function PostAction({ children, handleDelete }: PostActionProps) {
|
||||
disabled={!checkAnsUseAuthrt()}
|
||||
>
|
||||
답글
|
||||
</Button>
|
||||
</AuthorityButton>
|
||||
)}
|
||||
<Button size="lg" color="red" type="button" onClick={onDelete}>
|
||||
<AuthorityButton
|
||||
authority="delAuthrtYn"
|
||||
size="lg"
|
||||
color="red"
|
||||
type="button"
|
||||
onClick={onDelete}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
</AuthorityButton>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Generated
+22
@@ -99,6 +99,9 @@ importers:
|
||||
next:
|
||||
specifier: 15.3.0
|
||||
version: 15.3.0(react-dom@18.3.1)(react@18.3.1)
|
||||
next-themes:
|
||||
specifier: ^0.4.6
|
||||
version: 0.4.6(react-dom@18.3.1)(react@18.3.1)
|
||||
react-chartjs-2:
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0(chart.js@4.4.8)(react@18.3.1)
|
||||
@@ -108,6 +111,9 @@ importers:
|
||||
react-hook-form:
|
||||
specifier: ^7.54.2
|
||||
version: 7.54.2(react@18.3.1)
|
||||
sonner:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1(react-dom@18.3.1)(react@18.3.1)
|
||||
tailwindcss-animate:
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7(tailwindcss@3.4.17)
|
||||
@@ -238,6 +244,9 @@ importers:
|
||||
next-qrcode:
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1(react@18.3.1)
|
||||
next-themes:
|
||||
specifier: ^0.4.6
|
||||
version: 0.4.6(react-dom@18.3.1)(react@18.3.1)
|
||||
react-chartjs-2:
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0(chart.js@4.4.8)(react@18.3.1)
|
||||
@@ -247,6 +256,9 @@ importers:
|
||||
react-hook-form:
|
||||
specifier: ^7.54.2
|
||||
version: 7.54.2(react@18.3.1)
|
||||
sonner:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1(react-dom@18.3.1)(react@18.3.1)
|
||||
tailwindcss-animate:
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7(tailwindcss@3.4.17)
|
||||
@@ -7631,6 +7643,16 @@ packages:
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/next-themes@0.4.6(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
|
||||
peerDependencies:
|
||||
react: ^18.3.1
|
||||
react-dom: ^18.3.1
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/next@15.1.7(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg==}
|
||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||
|
||||
Reference in New Issue
Block a user