initial commit

This commit is contained in:
shafin-r
2025-07-03 01:43:25 +06:00
commit 5dc53b896e
279 changed files with 28956 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,111 @@
"use client";
import React from "react";
import { useEffect, useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Eye, Send, FileBox, Check, CircleUser } from "lucide-react";
import Image from "next/image";
import { Button } from "@/components/ui/button";
type CsvFile = {
name: string;
csvLink: string;
};
const ContactModal = () => {
const [csvFiles, setCsvFiles] = useState<CsvFile[]>([]);
console.log(csvFiles);
useEffect(() => {
const fetchCsvFiles = async () => {
try {
const response = await fetch("/api/fetchcsv");
if (!response.ok) {
throw new Error("Failed to fetch CSV files");
}
const data: CsvFile[] = await response.json();
setCsvFiles(data);
} catch (error) {
console.error("Error fetching CSV files:", error);
}
};
fetchCsvFiles();
}, []); // Only run on mount
return (
<div>
<Dialog>
<DialogTrigger className="px-4 bg-white text-black py-2 rounded-md">
<FileBox size={20} />
</DialogTrigger>
<DialogContent className="h-5/6 w-5/6 bg-[#222222]">
<DialogHeader>
<DialogTitle className="text-4xl tracking-tighter">
Select Contacts
</DialogTitle>
<DialogDescription>
Select a file to import contacts from.
</DialogDescription>
</DialogHeader>
<section className="flex gap-2">
<Select>
<SelectTrigger className="w-1/6 rounded-xl">
<SelectValue placeholder="Select Option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="gsheets">
<div className="flex items-center gap-1">
<Image
src="/icons/Sheets.svg"
alt="Google Sheets Icon"
width={20}
height={20}
/>
Google Sheets
</div>
</SelectItem>
<SelectItem value="system">
<div className="flex items-center gap-1">
<CircleUser size={20} />
Contact Manager
</div>
</SelectItem>
</SelectContent>
</Select>
<Select>
<SelectTrigger className="w-4/6 rounded-xl">
<SelectValue placeholder="Select File (.csv, .tsv)" />
</SelectTrigger>
<SelectContent>
{csvFiles.map((file) => (
<SelectItem key={file.name} value={file.name}>
{file.name}
</SelectItem>
))}
</SelectContent>
</Select>
<Button className="bg-[#34A853] h-9 rounded-xl w-1/6 text-white flex gap-2">
<Check />
Select
</Button>
</section>
</DialogContent>
</Dialog>
</div>
);
};
export default ContactModal;

View File

@ -0,0 +1,94 @@
"use client";
import * as React from "react";
import { Check, ChevronsUpDown } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
const attributes = [
{
value: "name",
label: "name",
},
{
value: "phone",
label: "phone",
},
{
value: "email",
label: "email",
},
{
value: "id",
label: "id",
},
{
value: "address",
label: "address",
},
];
export function ContactSelector() {
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState("");
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between bg-[#3d3d3d]"
>
{value
? attributes.find((attribute) => attribute.value === value)?.label
: "Select email field..."}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0 ">
<Command className="bg-[#222222]">
<CommandInput placeholder="Search attribute..." />
<CommandList>
<CommandEmpty>No attribute found.</CommandEmpty>
<CommandGroup>
{attributes.map((attribute) => (
<CommandItem
key={attribute.value}
value={attribute.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue);
setOpen(false);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
value === attribute.value ? "opacity-100" : "opacity-0"
)}
/>
{attribute.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
}

View File

@ -0,0 +1,87 @@
// components/RichTextEditor.tsx
import { useEditor, EditorContent, Editor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Heading from "@tiptap/extension-heading";
import Color from "@tiptap/extension-color";
import TextStyle from "@tiptap/extension-text-style";
import {
Bold,
Italic,
Strikethrough,
Heading1,
Heading2,
Heading3,
} from "lucide-react";
import { Toggle } from "@/components/ui/toggle";
const MenuBar: React.FC<{ editor: Editor | null }> = ({ editor }) => {
if (!editor) {
return null;
}
return (
<div className="toolbar pb-3 flex gap-2">
<Toggle onClick={() => editor.chain().focus().toggleBold().run()}>
<Bold className="h-4 w-4" />
</Toggle>
<Toggle
onClick={() => editor.chain().focus().toggleItalic().run()}
className={editor.isActive("italic") ? "is-active" : ""}
>
<Italic className="h-4 w-4" />
</Toggle>
<Toggle
onClick={() => editor.chain().focus().toggleStrike().run()}
className={editor.isActive("strike") ? "is-active" : ""}
>
<Strikethrough className="h-4 w-4" />
</Toggle>
{/* Heading Toggles */}
<Toggle
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
className={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
>
<Heading1 className="h-4 w-4" />
</Toggle>
<Toggle
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
className={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
>
<Heading2 className="h-4 w-4" />
</Toggle>
<Toggle
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
className={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
>
<Heading3 className="h-4 w-4" />
</Toggle>
</div>
);
};
const RichTextEditor: React.FC = () => {
const editor = useEditor({
extensions: [
StarterKit,
Heading.configure({
levels: [1, 2, 3],
}),
Color,
TextStyle,
],
content: "<p>Write your email here...</p>",
});
return (
<div className="">
<MenuBar editor={editor} />
<EditorContent
className="flex-1 overflow-y-auto overflow-x-auto h-[70vh]"
editor={editor}
/>
</div>
);
};
export default RichTextEditor;