Skip to content

Commit ed4d358

Browse files
authored
Merge pull request #103 from debatecore/98-copy-motion-button
[98] "Copy motion" button
2 parents db79473 + e9a30ee commit ed4d358

File tree

6 files changed

+80
-4
lines changed

6 files changed

+80
-4
lines changed

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,21 @@
1414
"@types/jest": "^29.5.12",
1515
"flag-icons": "^7.2.2",
1616
"jest": "^29.7.0",
17-
"jsdom": "24.1.0",
1817
"jest-environment-jsdom": "^29.7.0",
18+
"jsdom": "24.1.0",
1919
"next": "^14.1.0",
2020
"react": "^18",
2121
"react-dom": "^18",
2222
"react-use": "^17.5.0",
23+
"sonner": "^1.5.0",
2324
"ts-jest": "^29.1.4",
2425
"ts-node": "^10.9.2",
2526
"use-sound": "^4.0.1"
2627
},
2728
"devDependencies": {
29+
"@playwright/test": "^1.45.1",
2830
"@testing-library/dom": "^10.1.0",
2931
"@testing-library/react": "^16.0.0",
30-
"@playwright/test": "^1.45.1",
3132
"@types/node": "^20",
3233
"@types/react": "^18.3.3",
3334
"@types/react-dom": "^18.3.0",

src/components/MotionDisplay.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const MotionDisplay = ({ motion }: { motion: motion | null }) => {
88
return (
99
<section className="lg:w-[50vw] p-5 flex flex-col items-center self-center">
1010
<p className="text-xl xl:text-2xl max-w-[80vw] lg:max-w-[50vw] mb-5 text-balance">
11-
&quot;{motion && motion?.motion ? motion.motion : ""}&quot;
11+
{motion && motion?.motion ? motion.motion : ""}
1212
</p>
1313
{motion && motion.adinfo && (
1414
<section className="flex flex-col items-center mb-5 border-2 border-neutral-800 rounded-lg pt-2 p-4">
@@ -18,7 +18,9 @@ const MotionDisplay = ({ motion }: { motion: motion | null }) => {
1818
</span>
1919
{infoslideString}
2020
</section>
21-
<p className="text-justify max-w-[80vw] xl:max-w-[50vw]">{motion.adinfo}</p>
21+
<p className="text-justify max-w-[80vw] xl:max-w-[50vw]">
22+
{motion.adinfo}
23+
</p>
2224
</section>
2325
)}
2426
<p className="text-sm xl:text-base text-neutral-500 flex flex-col">

src/components/MotionGenerator.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ import { useLang } from "@/lib/useLang";
1313
import { LinkButton } from "./LinkButton";
1414
import { IconPlayCircle } from "./icons/PlayCircle";
1515
import { IconList } from "./icons/List";
16+
import { IconCopy } from "./icons/Copy";
17+
import { toast, Toaster } from "sonner";
1618

1719
const MotionGenerator = () => {
1820
const [motion, setMotion] = useState<motion | null>(null);
1921
const debateContext = useContext(DebateContext);
2022
const router = useRouter();
23+
const infoslideLabel = useLang("infoslide");
24+
const successfulCopyMessage = useLang("motionCopiedSuccess");
2125

2226
function generateMotion(): motion {
2327
const filteredMotions = motions.filter((motion) => {
@@ -29,6 +33,20 @@ const MotionGenerator = () => {
2933
return filteredMotions[Math.floor(Math.random() * filteredMotions.length)];
3034
}
3135

36+
function copyMotionToClipboard() {
37+
if (!motion?.motion || !motion.source || !motion.type) {
38+
return;
39+
}
40+
const infoslideLine = motion.adinfo
41+
? `${infoslideLabel}: ${motion.adinfo}\n`
42+
: "";
43+
const sourceLine = `~${motion.source}`;
44+
navigator.clipboard.writeText(
45+
`${motion.motion}\n${infoslideLine}${sourceLine}`
46+
);
47+
toast.success(successfulCopyMessage);
48+
}
49+
3250
function saveMotionToContext(): void {
3351
debateContext.setConf({
3452
...debateContext.conf,
@@ -53,12 +71,18 @@ const MotionGenerator = () => {
5371

5472
return (
5573
<div className="flex flex-col items-center text-center">
74+
<Toaster richColors position="bottom-center" />
5675
<section className="hidden xl:flex flex-col space-y-2 max-w-[400px]">
5776
<GenericButton
5877
text={useLang("debateMotionGeneratorRegenerate")}
5978
icon={IconDice}
6079
onClick={() => setMotion(generateMotion())}
6180
/>
81+
<GenericButton
82+
text={useLang("copyMotion")}
83+
icon={IconCopy}
84+
onClick={() => copyMotionToClipboard()}
85+
/>
6286
<GenericButton
6387
text={useLang("debateOverThisMotion")}
6488
icon={IconClock}
@@ -78,6 +102,11 @@ const MotionGenerator = () => {
78102
icon={IconDice}
79103
onClick={() => setMotion(generateMotion())}
80104
/>
105+
<GenericButton
106+
text={useLang("copyMotion")}
107+
icon={IconCopy}
108+
onClick={() => copyMotionToClipboard()}
109+
/>
81110
<GenericButton
82111
text={useLang("debateOverThisMotion")}
83112
icon={IconClock}

src/components/icons/Copy.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { iconprops } from "@/types/iconprops";
2+
3+
const IconCopy = (props: iconprops) => {
4+
return (
5+
<svg
6+
xmlns="http://www.w3.org/2000/svg"
7+
width="24"
8+
height="24"
9+
viewBox="0 0 24 24"
10+
fill="none"
11+
stroke="currentColor"
12+
stroke-width="2"
13+
stroke-linecap="round"
14+
stroke-linejoin="round"
15+
className={`feather ${props.moreClass}`}
16+
>
17+
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
18+
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
19+
</svg>
20+
);
21+
};
22+
23+
export { IconCopy };

src/data/strings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,5 +429,15 @@
429429
"en": "Debate finished!",
430430
"pl": "Debata zakończona!",
431431
"de": "Debatte geendet!"
432+
},
433+
"copyMotion": {
434+
"en": "Copy motion",
435+
"pl": "Skopiuj tezę",
436+
"de": "These kopieren"
437+
},
438+
"motionCopiedSuccess": {
439+
"en": "Motion copied to clipboard",
440+
"pl": "Teza skopiowana do schowka",
441+
"de": "These kopiert"
432442
}
433443
}

0 commit comments

Comments
 (0)