Skip to content

Commit

Permalink
Merge pull request #21 from git-init-priyanshu/nextjs
Browse files Browse the repository at this point in the history
Finishing changes
  • Loading branch information
git-init-priyanshu authored Sep 4, 2024
2 parents 7c2e790 + 3d89657 commit f406b5e
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 126 deletions.
19 changes: 10 additions & 9 deletions app/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { CircleCheck } from "lucide-react";

import { Card, CardContent, CardFooter } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
Expand All @@ -13,6 +12,7 @@ import AvatarList from "@/components/AvatarList";
import CardOptions from "./components/Options";
import prettifyDate from "@/helpers/prettifyDates";
import useClientSession from "@/lib/customHooks/useClientSession";
import useDebounce from "@/lib/customHooks/useDebounce";

type DocCardPropType = {
docId: string;
Expand All @@ -32,6 +32,11 @@ export default function DocCard({
}: DocCardPropType) {
const router = useRouter();

const debounce = useDebounce(async () => {
if (!inputRef.current || !session?.id) return;
await RenameDocument(docId, inputRef.current.value);
}, 1000)

const session = useClientSession();
localStorage.setItem("name", session.name as string);

Expand All @@ -52,15 +57,11 @@ export default function DocCard({
ref={inputRef}
value={name}
className="w-full text-md border-none focus-visible:bg-slate-50"
onChange={(e) => setName(e.target.value)}
/>
<CircleCheck
onClick={async () => {
if (!inputRef.current || !session?.id) return;
await RenameDocument(docId, inputRef.current.value);
onChange={(e) => {
setName(e.target.value);
debounce(e.target.value);
}}
className={`${title != name ? "" : "hidden"} size-4 text-slate-500 hover:cursor-pointer absolute right-3 top-1/2 transform -translate-y-1/2`}
></CircleCheck>
/>
</div>
<div className="flex items-center w-full justify-between">
<div className="flex gap-2 items-center">
Expand Down
1 change: 0 additions & 1 deletion app/components/Card/components/Options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
import { Button } from "@/components/ui/button";

import { DeleteDocument } from "../actions";
import useClientSession from "@/lib/customHooks/useClientSession";
import LoaderButton from "@/components/LoaderButton";

type CardOptionsPropType = {
Expand Down
19 changes: 3 additions & 16 deletions app/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import Image from "next/image";
import { Montserrat_Alternates as Montserrat } from "next/font/google"

import { SessionReturnType } from "@/lib/customHooks/ReturnType";
import getInitials from "@/helpers/getInitials";
import logo from "@/public/logo.svg";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import SearchBar from "./components/SearchBar";
import HeaderButtons from "./components/HeaderButtons";

Expand All @@ -18,25 +16,14 @@ const roboto = Montserrat({
type HeaderPropType = Pick<SessionReturnType, "name" | "image">;
export default function Header({ image, name }: HeaderPropType) {
return (
<div className="flex border-b bg-white justify-between items-center py-2 px-4">
<div className="flex border-b bg-white justify-between items-center py-2 px-4 sticky top-0 z-50">
<div className="flex gap-2 items-end justify-center">
<Image src={logo} width={45} alt="logo" />
<p className={`${roboto.className} text-lg`}>DocX</p>
<p className={`${roboto.className} text-lg text-neutral-600`}>DocX</p>
{/* <Image src={logo} width={45} alt="logo" /> */}
</div>
<SearchBar />
<HeaderButtons />
{process.env.NODE_ENV === "production" ? (
<></>
) : (
<Avatar className="size-8">
{image ? (
<AvatarImage src={image} />
) : (
<AvatarFallback>{getInitials(name ?? "")}</AvatarFallback>
)}
</Avatar>
)}
<HeaderButtons image={image} name={name} />
</div>
);
}
66 changes: 44 additions & 22 deletions app/components/Header/components/HeaderButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@ import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { CloudUpload, LogOut, PlusIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { CreateNewDocument, LogoutAction } from "../actions";
import useClientSession from "@/lib/customHooks/useClientSession";
import { Button } from "@/components/ui/button";
import { SessionReturnType } from "@/lib/customHooks/ReturnType";
import LoaderButton from "@/components/LoaderButton";
import getInitials from "@/helpers/getInitials";
import { Popover } from "@/components/ui/popover";
import { PopoverContent, PopoverTrigger } from "@radix-ui/react-popover";

export default function HeaderButtons() {
type HeaderBtnPropType = Pick<SessionReturnType, "name" | "image">;
export default function HeaderButtons({ image, name }: HeaderBtnPropType) {
const router = useRouter();

const session = useClientSession();

const [isLoading, setIsLoading] = useState(false);

const createDocument = async () => {
setIsLoading(true);

if (!session?.id) return;
const response = await CreateNewDocument();
if (response.success) {
setIsLoading(false);
Expand All @@ -34,7 +36,6 @@ export default function HeaderButtons() {

const logout = async () => {
const response = await LogoutAction();
console.log(response);
if (response.success) {
toast.success("Successfully logged out");
router.push("/api/auth/signin");
Expand All @@ -45,13 +46,16 @@ export default function HeaderButtons() {
return (
<div className="flex gap-4">
<div className="flex md:gap-4">
<Button
variant="outline"
className="flex gap-2 text-blue-500 hover:text-blue-500 hover:border-blue-200 rounded-l-full md:rounded-full"
>
<CloudUpload size={15} />
<p className="hidden md:block">Upload</p>
</Button>
{process.env.NODE_ENV === "development" ?
<Button
variant="outline"
className="flex gap-2 text-blue-500 hover:text-blue-500 hover:border-blue-200 rounded-l-full md:rounded-full"
>
<CloudUpload size={15} />
<p className="hidden md:block">Upload</p>
</Button>
: <></>
}
<LoaderButton
className="bg-blue-500 text-white hover:bg-blue-600 rounded-r-full md:rounded-full"
onClickFunc={createDocument}
Expand All @@ -61,13 +65,31 @@ export default function HeaderButtons() {
<p className="hidden md:block">Create New</p>
</LoaderButton>
</div>
<Button
variant="outline"
className="flex gap-2 text-blue-500 hover:text-blue-500 hover:border-blue-200 rounded-full"
onClick={logout}
>
<LogOut size={15} />
</Button>
</div>
<Popover>
<PopoverTrigger>
<div className="relative flex justify-center items-center bg-blue-50 size-8 rounded-full ring-blue-100 hover:ring">
<p>{getInitials(name ?? "X")}</p>
</div>
{image ? (
<Avatar className="size-8 absolute transform -translate-y-full">
<AvatarImage src={image} />
</Avatar>
) : (<></>)}
</PopoverTrigger>
<PopoverContent
className="flex flex-col p-0 py-1 text-left w-min bg-white shadow-md"
>
<Button
// id={item.title}
variant="ghost"
className="gap-2 justify-start"
onClick={logout}
>
<LogOut size={20} color="#48acf9" strokeWidth={1.5} />
<p className="text-neutral-600">Logout</p>
</Button>
</PopoverContent>
</Popover>
</div >
);
}
49 changes: 20 additions & 29 deletions app/components/Header/components/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { Search, X } from "lucide-react";
import { debounce } from "lodash";
import Image from "next/image";

import { Input } from "@/components/ui/input";
import prettifyDate from "@/helpers/prettifyDates";
import doc from "@/public/output-onlinepngtools.svg";
import useDebounce from "@/lib/customHooks/useDebounce";

import { SearchDocAction } from "../actions";

Expand All @@ -28,6 +28,14 @@ type SearchResponse = {
export default function SearchBar() {
const router = useRouter();

const debounce = useDebounce(
async (value: string) => {
if (!searchValue) return;
setIsSearching(true);
setSearchResponse(await SearchDocAction(value));
setIsSearching(false);
}, 500);

const searchedResponseRef = useRef<HTMLDivElement>(null);

const [searchResponse, setSearchResponse] = useState<
Expand All @@ -37,21 +45,6 @@ export default function SearchBar() {
const [isFocused, setIsFocused] = useState(false);
const [isSearching, setIsSearching] = useState(false);

const search = useCallback(
async (value: string) => {
if (!searchValue) return;
setIsSearching(true);
setSearchResponse(await SearchDocAction(value));
setIsSearching(false);
},
[searchValue],
);

const debouncedSearch = useMemo(
() => debounce((value: string) => search(value), 500),
[search],
);

const handleDocumentClick = (e: any) => {
if (
searchedResponseRef.current &&
Expand All @@ -73,17 +66,17 @@ export default function SearchBar() {
>
<div className="relative">
<Input
className={`${
isFocused && searchResponse
? "rounded-t-3xl rounded-b-none"
: "rounded-full"
} px-8 `}
className={`${isFocused && searchResponse
? "rounded-t-3xl rounded-b-none"
: "rounded-full"
} px-8 `}
onFocus={() => setIsFocused(true)}
value={searchValue}
onChange={(e) => {
setSearchValue(e.target.value);
if (!e.target.value) return setSearchResponse(undefined);
debouncedSearch(e.target.value);
// debouncedSearch(e.target.value);
debounce(e.target.value);
}}
placeholder="Search documents..."
/>
Expand All @@ -94,17 +87,15 @@ export default function SearchBar() {
<X
size={20}
onClick={() => setSearchValue("")}
className={`${
!searchValue ? "hidden" : "block"
} absolute text-slate-500 right-0 top-1/2 transform -translate-y-1/2 mr-2 cursor-pointer`}
className={`${!searchValue ? "hidden" : "block"
} absolute text-slate-500 right-0 top-1/2 transform -translate-y-1/2 mr-2 cursor-pointer`}
/>
</div>

<div
ref={searchedResponseRef}
className={`${
isFocused && searchResponse ? "block" : "hidden"
} absolute shadow-md overflow-hidden border border-t-0 bg-white w-full rounded-b-3xl`}
className={`${isFocused && searchResponse ? "block" : "hidden"
} absolute shadow-md overflow-hidden border border-t-0 bg-white w-full rounded-b-3xl`}
>
{isSearching ? (
<div className="p-3 flex items-center gap-2 justify-center text-center text-neutral-500">
Expand Down
2 changes: 1 addition & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import "./globals.css";
const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Docx",
title: "DocX",
description:
"An open-source alternative to Google Docs, that lets you write and customize your docs collaboratively with others",
};
Expand Down
1 change: 1 addition & 0 deletions app/writer/[id]/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const UpdateThumbnail = async (id: any, thumbnail: string) => {
error: "User is not logged in",
};

console.log(process.env.BACKEND_SERVER_URL)
const response = await fetch(`${process.env.BACKEND_SERVER_URL}/push-to-quque`, {
method: "POST",
headers: {
Expand Down
Loading

0 comments on commit f406b5e

Please sign in to comment.