Skip to content

Commit

Permalink
Words can now be edited or deleted.
Browse files Browse the repository at this point in the history
Folders can now be deleted as well.
The sections for words and folders can be collapsed to provide more space.
  • Loading branch information
Your Name committed Sep 11, 2024
1 parent 0985c04 commit bb6d136
Show file tree
Hide file tree
Showing 16 changed files with 773 additions and 89 deletions.
27 changes: 27 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,31 @@
.folder {
@apply w-60 h-14 bg-gray-700 flex items-center rounded-md px-2 overflow-hidden gap-2 text-slate-300 cursor-pointer hover:bg-gray-600 select-none;
}
.CollapsibleContent {
overflow: hidden;
}
.CollapsibleContent[data-state="open"] {
animation: slideDown 300ms ease-out;
}
.CollapsibleContent[data-state="closed"] {
animation: slideUp 300ms ease-out;
}

@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--radix-collapsible-content-height);
}
}

@keyframes slideUp {
from {
height: var(--radix-collapsible-content-height);
}
to {
height: 0;
}
}
}
4 changes: 2 additions & 2 deletions components/AddNewFolder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { PlusIcon } from "lucide-react";
import { useState } from "react";
import AddNewFolderDialog from "./AddNewFolderDialog";
import FolderDialog from "./FolderDialog";

const AddNewFolder = ({
path,
Expand All @@ -20,7 +20,7 @@ const AddNewFolder = ({
Add Folder <PlusIcon />
</DialogTrigger>
<DialogContent>
<AddNewFolderDialog
<FolderDialog
setOpen={setOpen}
path={path}
setFolders={setFolders}
Expand Down
4 changes: 2 additions & 2 deletions components/AddNewWord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { PlusIcon } from "lucide-react";
import { useState } from "react";
import AddNewWordDialog from "./AddNewWordDialog";
import WordDialog from "./WordDialog";

const AddNewWord = ({
path,
Expand All @@ -20,7 +20,7 @@ const AddNewWord = ({
Add Word <PlusIcon />
</DialogTrigger>
<DialogContent>
<AddNewWordDialog
<WordDialog
setOpen={setOpen}
path={path}
setWords={setWords}
Expand Down
59 changes: 49 additions & 10 deletions components/Folder.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
import { deleteDocument } from "@/lib/actions/user.actions";
import { Folder as FolderIcon } from "lucide-react";
const Folder = ({ name }: FolderProps) => {
import Link from "next/link";
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuTrigger,
} from "./ui/context-menu";
const Folder = ({
folder,
setFolders,
folderHref,
}: {
folder: FolderType;
setFolders: React.Dispatch<React.SetStateAction<FolderType[]>>;
folderHref: string;
}) => {
const handleDelete = async () => {
const deleteConfirm = confirm(
"Are you sure you want to delete this word?"
);
if (!deleteConfirm) return;
const success = await deleteDocument("folder", folder.$id);
if (success) {
setFolders((prevFolders) =>
prevFolders.filter((f) => f.$id !== folder.$id)
);
}
};
return (
<div className="folder" title={name}>
<div className="icon">
<FolderIcon
fill="rgb(255,255,255,0.6)"
color="rgb(255,255,255,0.6)"
/>
</div>
<div className="flex-1 overflow-hidden">{name}</div>
</div>
<ContextMenu>
<ContextMenuTrigger>
<Link href={folderHref}>
<div className="folder" title={folder.name}>
<div className="icon">
<FolderIcon
fill="rgb(255,255,255,0.6)"
color="rgb(255,255,255,0.6)"
/>
</div>
<div className="flex-1 overflow-hidden">
{folder.name}
</div>
</div>
</Link>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem onClick={handleDelete}>Delete</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
);
};

Expand Down
21 changes: 10 additions & 11 deletions components/AddNewFolderDialog.tsx → components/FolderDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
import { addNewFolder } from "@/lib/actions/user.actions";
import { useLanguagesStore } from "@/store/userLanguages";
import { Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Button } from "./ui/button";
import { DialogFooter, DialogHeader, DialogTitle } from "./ui/dialog";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
const AddNewFolderDialog = ({
const FolderDialog = ({
setOpen,
path,
setFolders,
Expand All @@ -18,21 +17,21 @@ const AddNewFolderDialog = ({
setFolders: React.Dispatch<React.SetStateAction<FolderType[]>>;
}) => {
const { currentLanguage } = useLanguagesStore();
const [folder, setFolder] = useState("");
const [folderName, setFolderName] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState("");
const router = useRouter();

const handleAddNewFolder = async () => {
setIsLoading(true);
if (folder === "") {
if (folderName === "") {
setIsLoading(false);

setError("Please enter folder Name");
return;
}

const addedFolder = await addNewFolder(
folder,
path,
folderName,
path!,
currentLanguage.$id
);
if (addedFolder.error) {
Expand Down Expand Up @@ -67,9 +66,9 @@ const AddNewFolderDialog = ({
<Input
id="folder"
className="focus-visible:ring-transparent"
value={folder}
value={folderName}
placeholder="Folder Name"
onChange={(e) => setFolder(e.target.value)}
onChange={(e) => setFolderName(e.target.value)}
/>
</div>
</div>
Expand All @@ -95,4 +94,4 @@ const AddNewFolderDialog = ({
);
};

export default AddNewFolderDialog;
export default FolderDialog;
52 changes: 37 additions & 15 deletions components/FoldersContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
"use client";
import Link from "next/link";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { ChevronDown, ChevronRight } from "lucide-react";
import { useState } from "react";
import AddNewFolder from "./AddNewFolder";
import Folder from "./Folder";

Expand All @@ -12,22 +18,38 @@ const FoldersContainer = ({
path: string;
setFolders: React.Dispatch<React.SetStateAction<FolderType[]>>;
}) => {
const [isCollapsibleOpen, setIsCollapsibleOpen] = useState(true);
return (
<div className="folders-container">
<div className="font-semibold mb-2">Folders</div>
<div className="flex flex-wrap flex-1 gap-3">
{folders.map((f) => {
const folderHref = `${f.path}${f.name
.trim()
.replace(" ", "-")}`;
return (
<Link href={folderHref} key={f.$id}>
<Folder name={f.name} />
</Link>
);
})}
</div>
<AddNewFolder path={path} setFolders={setFolders} />
<Collapsible
open={isCollapsibleOpen}
onOpenChange={setIsCollapsibleOpen}
>
<CollapsibleTrigger>
<div className="font-semibold mb-2 flex gap-2 hover:bg-slate-400 rounded-sm p-1 pr-2">
{isCollapsibleOpen ? <ChevronDown /> : <ChevronRight />}{" "}
Folders
</div>
</CollapsibleTrigger>
<CollapsibleContent className="CollapsibleContent">
<div className="flex flex-wrap flex-1 gap-3">
{folders.map((f) => {
const folderHref = `${f.path}${f.name
.trim()
.replaceAll(" ", "-")}`;
return (
<Folder
key={f.$id}
folder={f}
setFolders={setFolders}
folderHref={folderHref}
/>
);
})}
</div>
</CollapsibleContent>
<AddNewFolder path={path} setFolders={setFolders} />
</Collapsible>
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions components/PathDataPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const PathDataPage = ({ path, user }: { path: string; user: any }) => {
const { folders: fetchedFolders, words: fetchedWords } =
await getPathData(user.$id, currentLanguage.$id, path);

console.log({ fetchedFolders, fetchedWords });
setFolders(fetchedFolders);
setWords(fetchedWords);
setisLoading(false);
Expand Down
22 changes: 12 additions & 10 deletions components/UserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ const UserCard = ({ user }: userCardProps) => {
</div>
</div>
<div className="logout" title={t("LogOut")} onClick={handleLogOut}>
{isLoading ? (
<Loader2 size={20} className="animate-spin" />
) : (
<Image
src="/icons/logout.svg"
width="24"
height="24"
alt="logout"
/>
)}
<button>
{isLoading ? (
<Loader2 size={20} className="animate-spin" />
) : (
<Image
src="/icons/logout.svg"
width="24"
height="24"
alt="logout"
/>
)}
</button>
</div>
</div>
);
Expand Down
84 changes: 67 additions & 17 deletions components/WordCard.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,83 @@
"use client";
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu";
import { deleteDocument } from "@/lib/actions/user.actions";
import { useLanguagesStore } from "@/store/userLanguages";
import { Volume2 } from "lucide-react";
import { useState } from "react";
import WordDialog from "./WordDialog";
import { Dialog, DialogContent } from "./ui/dialog";

const WordCard = ({ firstLang, secondLang }: WordCardProps) => {
const WordCard = ({
word,
setWords,
}: {
word: WordType;
setWords: React.Dispatch<React.SetStateAction<WordType[]>>;
}) => {
const { currentLanguage } = useLanguagesStore();
const [editDialogOpen, setEditDialogOpen] = useState(false);
const handleListen = () => {
const speech = new SpeechSynthesisUtterance(secondLang);
const speech = new SpeechSynthesisUtterance(word.secondLang);
speech.lang = currentLanguage.code;

console.log(window.speechSynthesis.getVoices());
speechSynthesis.speak(speech);
};

const handleDelete = async () => {
const deleteConfirm = confirm(
"Are you sure you want to delete this word?"
);
if (!deleteConfirm) return;
const success = await deleteDocument("word", word.$id);
if (success) {
setWords((prevWords) =>
prevWords.filter((w) => w.$id !== word.$id)
);
}
};
return (
<div className="word-card">
<div className="first-lang">{firstLang}</div>
<div className="second-lang">{secondLang}</div>
<div onClick={handleListen}>listen</div>
<div
className="flex mt-3 justify-center items-center cursor-pointer"
onClick={handleListen}
>
<div className="">
<Volume2 />
<ContextMenu>
<ContextMenuTrigger>
<Dialog open={editDialogOpen} onOpenChange={setEditDialogOpen}>
<DialogContent>
<WordDialog
isEdit
wordId={word.$id}
setOpen={setEditDialogOpen}
setWords={setWords}
/>
</DialogContent>
</Dialog>
<div className="word-card">
<div className="first-lang">{word.firstLang}</div>
<div className="second-lang">{word.secondLang}</div>
<div onClick={handleListen}>listen</div>
<div
className="flex mt-3 justify-center items-center cursor-pointer"
onClick={handleListen}
>
<div className="">
<Volume2 />
</div>
<span className="inline-block ml-2 font-semibold text-lg">
Listen
</span>
</div>
</div>
<span className="inline-block ml-2 font-semibold text-lg">
Listen
</span>
</div>
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem onClick={() => setEditDialogOpen(true)}>
Edit
</ContextMenuItem>
<ContextMenuItem onClick={handleDelete}>Delete</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
);
};

Expand Down
Loading

0 comments on commit bb6d136

Please sign in to comment.