Skip to content

Commit 9d1c147

Browse files
committed
Various UI / bug fixes
1 parent 4ae1f46 commit 9d1c147

8 files changed

Lines changed: 115 additions & 94 deletions

File tree

src/app/(main)/page.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
import { Icons } from "@/components/ui/icons";
1+
import {Icons} from "@/components/ui/icons";
22
import VaultPage from "@/components/ui/vault/vault";
33
import prismadb from "@/lib/prismadb";
4-
import { auth } from "@clerk/nextjs/server";
5-
import { Loader } from "lucide-react";
4+
import {RedirectToSignIn,SignedOut} from "@clerk/nextjs";
5+
import {auth} from "@clerk/nextjs/server";
66

77
const Page = async () => {
88
const { userId } = await auth();
99

1010
if (!userId) {
1111
return (
12-
<div className="h-full w-full flex justify-center items-center">
13-
<Icons.logo />
14-
<Loader className="text-black animate-spin" />
12+
<div className="h-screen w-[calc(100vw-var(--sidebar-width))] flex justify-center items-center animate-pulse">
13+
<Icons.logo className="w-40 h-40" />
14+
<h1 className="font-bold tracking-tig text-7xl">Authenticating</h1>
15+
16+
<SignedOut>
17+
<RedirectToSignIn />
18+
</SignedOut>
1519
</div>
1620
);
1721
}

src/app/api/passwords/[passwordId]/route.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import prismadb from "@/lib/prismadb";
2-
import { auth } from "@clerk/nextjs/server";
3-
import { NextResponse } from "next/server";
2+
import {auth} from "@clerk/nextjs/server";
3+
import {NextResponse} from "next/server";
44

5-
export async function DELETE(req: Request, props: { params: Promise<{ passwordId: Promise<string> }> }) {
5+
export async function DELETE(
6+
req: Request,
7+
props: { params: Promise<{ passwordId: Promise<string> }> }
8+
) {
69
const params = await props.params;
710
try {
811
const { userId } = await auth();
@@ -40,7 +43,10 @@ export async function DELETE(req: Request, props: { params: Promise<{ passwordId
4043
}
4144
}
4245

43-
export async function PATCH(req: Request, props: { params: Promise<{ passwordId: Promise<string> }> }) {
46+
export async function PATCH(
47+
req: Request,
48+
props: { params: Promise<{ passwordId: Promise<string> }> }
49+
) {
4450
const params = await props.params;
4551
try {
4652
const { userId } = await auth();

src/components/ui/app-sidebar.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import {
1818
SidebarMenuButton,
1919
SidebarMenuItem,
2020
} from "@/components/ui/sidebar";
21-
import { useSidebar } from "@/hooks/use-sidebar-tab";
22-
import { UserButton, useUser } from "@clerk/nextjs";
23-
import { Icons } from "./icons";
24-
import { Separator } from "./separator";
21+
import {useSidebar} from "@/hooks/use-sidebar-tab";
22+
import {UserButton,useUser} from "@clerk/nextjs";
23+
import {Icons} from "./icons";
24+
import {Separator} from "./separator";
2525

2626
const items = [
2727
{

src/components/ui/button.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import * as React from "react"
2-
import { Slot } from "@radix-ui/react-slot"
3-
import { cva, type VariantProps } from "class-variance-authority"
1+
import {Slot} from "@radix-ui/react-slot";
2+
import {cva,type VariantProps} from "class-variance-authority";
3+
import * as React from "react";
44

5-
import { cn } from "@/lib/utils"
5+
import {cn} from "@/lib/utils";
66

77
const buttonVariants = cva(
88
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
@@ -31,26 +31,27 @@ const buttonVariants = cva(
3131
size: "default",
3232
},
3333
}
34-
)
34+
);
3535

3636
export interface ButtonProps
3737
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
3838
VariantProps<typeof buttonVariants> {
39-
asChild?: boolean
39+
asChild?: boolean;
4040
}
4141

4242
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
4343
({ className, variant, size, asChild = false, ...props }, ref) => {
44-
const Comp = asChild ? Slot : "button"
44+
const Comp = asChild ? Slot : "button";
4545
return (
4646
<Comp
4747
className={cn(buttonVariants({ variant, size, className }))}
4848
ref={ref}
4949
{...props}
5050
/>
51-
)
51+
);
5252
}
53-
)
54-
Button.displayName = "Button"
53+
);
54+
Button.displayName = "Button";
55+
56+
export {Button,buttonVariants};
5557

56-
export { Button, buttonVariants }

src/components/ui/sidebar.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
"use client"
22

3+
import {Slot} from "@radix-ui/react-slot"
4+
import {VariantProps,cva} from "class-variance-authority"
5+
import {PanelLeft} from "lucide-react"
36
import * as React from "react"
4-
import { Slot } from "@radix-ui/react-slot"
5-
import { VariantProps, cva } from "class-variance-authority"
6-
import { PanelLeft } from "lucide-react"
7-
8-
import { Button } from "@/components/ui/button"
9-
import { Input } from "@/components/ui/input"
10-
import { Separator } from "@/components/ui/separator"
11-
import { Sheet, SheetContent } from "@/components/ui/sheet"
12-
import { Skeleton } from "@/components/ui/skeleton"
7+
8+
import {Button} from "@/components/ui/button"
9+
import {Input} from "@/components/ui/input"
10+
import {Separator} from "@/components/ui/separator"
11+
import {Sheet,SheetContent} from "@/components/ui/sheet"
12+
import {Skeleton} from "@/components/ui/skeleton"
1313
import {
1414
Tooltip,
1515
TooltipContent,
@@ -759,5 +759,5 @@ export {
759759
SidebarRail,
760760
SidebarSeparator,
761761
SidebarTrigger,
762-
useSidebar,
762+
useSidebar
763763
}

src/components/ui/vault/password-vault.tsx

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,16 @@
11
"use client";
22

3-
import { usePasswordModal } from "@/hooks/use-password-modal";
4-
import { useUser } from "@clerk/nextjs";
5-
import { PasswordItem, Prisma } from "@prisma/client";
3+
import {usePasswordModal} from "@/hooks/use-password-modal";
4+
import {useUser} from "@clerk/nextjs";
5+
import {PasswordItem,Prisma} from "@prisma/client";
66
import CryptoJS from "crypto-js";
7-
import {
8-
AlertTriangle,
9-
Check,
10-
Edit,
11-
ExternalLink,
12-
Eye,
13-
EyeOff,
14-
Globe,
15-
Loader,
16-
Mail,
17-
PenSquare,
18-
Plus,
19-
Search,
20-
Timer,
21-
User,
22-
Zap,
23-
} from "lucide-react";
24-
import { useEffect, useState } from "react";
25-
import toast from "react-hot-toast";
26-
import { Button } from "../button";
27-
import { Card } from "../card";
28-
import { ScrollArea } from "../scroll-area";
29-
import { Sheet, SheetContent } from "../sheet";
30-
import { DetailsPanel } from "./password/details-panel";
7+
import {Loader,Plus,Search} from "lucide-react";
8+
import {useEffect,useState} from "react";
9+
import {Button} from "../button";
10+
import {Card} from "../card";
11+
import {ScrollArea} from "../scroll-area";
12+
import {Sheet,SheetContent} from "../sheet";
13+
import {DetailsPanel} from "./password/details-panel";
3114

3215
interface PasswordVaultProps {
3316
user: Prisma.UserGetPayload<{
@@ -46,7 +29,9 @@ const PasswordVault: React.FC<PasswordVaultProps> = ({ user }) => {
4629
const [loading, setLoading] = useState(true);
4730
const [data, setData] = useState<any[]>([]);
4831
const [isDetailsOpen, setIsDetailsOpen] = useState(false);
49-
const [selectedVault, setSelectedVault] = useState<PasswordItem | null | undefined>(undefined);
32+
const [selectedVault, setSelectedVault] = useState<
33+
PasswordItem | null | undefined
34+
>(undefined);
5035

5136
useEffect(() => {
5237
const handleResize = () => {
@@ -180,14 +165,19 @@ const PasswordVault: React.FC<PasswordVaultProps> = ({ user }) => {
180165
</ScrollArea>
181166
</main>
182167

183-
{/* Details panel */}
184-
<aside className="hidden md:block border-l w-2/3">
185-
<DetailsPanel
186-
selectedVault={selectedVault!}
187-
onClose={() => setIsDetailsOpen(false)}
188-
encrypt={encrypt}
189-
setData={setSelectedVault}
190-
/>
168+
<aside
169+
className={`hidden md:block border-l ${
170+
data.length > 0 ? "w-2/3" : "w-0"
171+
}`}
172+
>
173+
{data.length > 0 && (
174+
<DetailsPanel
175+
selectedVault={selectedVault!}
176+
onClose={() => setIsDetailsOpen(false)}
177+
encrypt={encrypt}
178+
setData={setSelectedVault}
179+
/>
180+
)}
191181
</aside>
192182

193183
{/* Details panel for mobile */}

src/components/ui/vault/password/details-panel.tsx

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import { useState, useEffect } from "react";
1+
import {PasswordItem} from "@prisma/client";
2+
import axios from "axios";
23
import {
34
Check,
45
Edit,
5-
User,
6-
PenSquare,
76
ExternalLink,
87
Globe,
9-
Zap,
8+
PenSquare,
109
Trash,
10+
User,
11+
Zap,
1112
} from "lucide-react";
13+
import {useEffect,useState} from "react";
1214
import toast from "react-hot-toast";
13-
import { PasswordItem } from "@prisma/client";
14-
import { Button } from "../../button";
15-
import axios from "axios";
15+
import {Button} from "../../button";
1616

1717
interface DetailsPanelProps {
1818
selectedVault: PasswordItem | null;
@@ -38,8 +38,20 @@ export const DetailsPanel: React.FC<DetailsPanelProps> = ({
3838
});
3939

4040
const handleCopy = (text: string, field: string) => {
41-
navigator.clipboard.writeText(text);
42-
toast("Copied!");
41+
if (!text) {
42+
toast.error(`${field} is empty!`);
43+
return;
44+
}
45+
46+
navigator.clipboard
47+
.writeText(text)
48+
.then(() => {
49+
toast(`${field} copied!`);
50+
})
51+
.catch((error) => {
52+
toast.error("Failed to copy!");
53+
console.error("Clipboard copy failed: ", error);
54+
});
4355
};
4456

4557
const handleEdit = (field: string, value: string) => {
@@ -109,7 +121,7 @@ export const DetailsPanel: React.FC<DetailsPanelProps> = ({
109121
<Button variant="outline" size="icon" onClick={() => handleDelete()}>
110122
<Trash />
111123
</Button>
112-
<Button
124+
<Button
113125
variant="outline"
114126
size="icon"
115127
onClick={() => (isEditing ? handleSave() : setIsEditing(true))}
@@ -122,7 +134,6 @@ export const DetailsPanel: React.FC<DetailsPanelProps> = ({
122134
</Button>
123135
</div>
124136
<div>
125-
{/* Username */}
126137
<button
127138
className="w-full group text-left border rounded-tr-xl rounded-tl-xl"
128139
onClick={() => handleCopy(selectedVault?.username ?? "", "Username")}
@@ -179,7 +190,6 @@ export const DetailsPanel: React.FC<DetailsPanelProps> = ({
179190
</div>
180191
</button>
181192

182-
{/* Website */}
183193
<button
184194
className="w-full group text-left border rounded-bl-xl rounded-br-xl"
185195
onClick={() => handleCopy(selectedVault?.website ?? "", "Website")}
@@ -204,14 +214,24 @@ export const DetailsPanel: React.FC<DetailsPanelProps> = ({
204214
</div>
205215
</div>
206216
<div>
207-
<Button
208-
variant="ghost"
209-
size="icon"
210-
className="text-muted-foreground hover:text-foreground"
211-
onClick={() => window.open(selectedVault?.website, "_blank")}
217+
<div
218+
className="text-muted-foreground hover:text-foreground cursor-pointer"
219+
onClick={(e) => {
220+
e.stopPropagation();
221+
if (selectedVault?.website) {
222+
const url =
223+
selectedVault.website.startsWith("http://") ||
224+
selectedVault.website.startsWith("https://")
225+
? selectedVault.website
226+
: `https://${selectedVault.website}`;
227+
window.open(url, "_blank");
228+
} else {
229+
toast.error("No website URL available!");
230+
}
231+
}}
212232
>
213233
<ExternalLink className="h-4 w-4" />
214-
</Button>
234+
</div>
215235
</div>
216236
</div>
217237
</button>

src/components/ui/vault/vault.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"use client";
22

3-
import { useSidebar } from "@/hooks/use-sidebar-tab";
4-
import { useVaultModal } from "@/hooks/use-vault-modal";
5-
import { Prisma } from "@prisma/client";
6-
import { useEffect } from "react";
7-
import { Icons } from "../icons";
3+
import {useSidebar} from "@/hooks/use-sidebar-tab";
4+
import {useVaultModal} from "@/hooks/use-vault-modal";
5+
import {Prisma} from "@prisma/client";
6+
import {useEffect} from "react";
7+
import {Icons} from "../icons";
88
import PasswordVault from "./password-vault";
99

1010
interface VaultPageProps {

0 commit comments

Comments
 (0)