uwu rawr :3

This commit is contained in:
g
2025-02-14 20:36:48 +00:00
parent 1db930d9a3
commit 1804e52e83
3 changed files with 174 additions and 23 deletions

View File

@@ -5,16 +5,17 @@ import { useRouter } from "next/navigation";
import Layout from "@/components/layout/layout";
import { Button } from "@/components/ui/button";
import { Product } from "@/models/products";
import { Plus } from "lucide-react";
import { Plus, Upload } from "lucide-react";
import {
fetchProductData,
saveProductData,
saveProductImage,
deleteProductData,
} from "@/lib/productData";
import { ProductModal } from "@/components/modals/product-modal";
import ProductTable from "@/components/tables/product-table";
import { Category } from "@/models/categories"
import { Category } from "@/models/categories";
import ImportProductsModal from "@/components/modals/import-products-modal";
import { ProductModal } from "@/components/modals/product-modal";
export default function ProductsPage() {
@@ -33,6 +34,8 @@ export default function ProductsPage() {
pricing: [{ minQuantity: 1, pricePerUnit: 0 }],
image: null,
});
const [importModalOpen, setImportModalOpen] = useState(false);
const [addProductOpen, setAddProductOpen] = useState(false);
// Fetch products and categories
useEffect(() => {
@@ -214,14 +217,23 @@ export default function ProductsPage() {
return (
<Layout>
<div className="space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-2xl font-semibold text-gray-900 dark:text-white">
Product Inventory
</h1>
<Button onClick={handleAddNewProduct}>
<Plus className="mr-2 h-5 w-5" />
Add Product
</Button>
<div className="flex items-center justify-between mb-6">
<h1 className="text-2xl font-semibold">Product Inventory</h1>
<div className="flex items-center gap-3">
<Button
onClick={() => setImportModalOpen(true)}
variant="outline"
className="gap-2"
disabled={true}
>
<Upload className="h-4 w-4" />
Import Products
</Button>
<Button onClick={() => setAddProductOpen(true)} className="gap-2">
<Plus className="h-4 w-4" />
Add Product
</Button>
</div>
</div>
<ProductTable
@@ -233,18 +245,26 @@ export default function ProductsPage() {
/>
<ProductModal
open={modalOpen}
onClose={() => setModalOpen(false)}
open={addProductOpen}
onClose={() => setAddProductOpen(false)}
onSave={handleSaveProduct}
productData={productData}
categories={categories}
editing={editing}
handleChange={handleChange}
handleTieredPricingChange={handleTieredPricingChange}
handleAddTier={handleAddTier} // ✅ Ensure this is passed
handleRemoveTier={handleRemoveTier} // ✅ Ensure this is passed
handleAddTier={handleAddTier}
handleRemoveTier={handleRemoveTier}
setProductData={setProductData}
/>
<ImportProductsModal
open={importModalOpen}
setOpen={setImportModalOpen}
onImportComplete={() => {
setProducts(products);
}}
/>
</div>
</Layout>
);

View File

@@ -138,14 +138,12 @@ export default function StorefrontPage() {
fetchStorefront();
}, []);
// ✅ Handle Form Input Changes
const handleInputChange = (
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
setStorefront({ ...storefront, [e.target.name]: e.target.value });
};
// ✅ Save Storefront Changes
const saveStorefront = async () => {
try {
setSaving(true);
@@ -161,7 +159,6 @@ export default function StorefrontPage() {
return (
<Layout>
<div className="max-w-4xl mx-auto p-6 space-y-6">
{/* PGP Key Section */}
<div className="bg-white dark:bg-[#0F0F12] rounded-xl shadow-lg p-6 border dark:border-zinc-700">
<div className="flex items-center gap-3 mb-4">
<Key className="h-6 w-6 text-purple-600 dark:text-purple-400" />
@@ -177,7 +174,6 @@ export default function StorefrontPage() {
/>
</div>
{/* Telegram Section */}
<div className="bg-white dark:bg-[#0F0F12] rounded-xl shadow-lg p-6 border dark:border-zinc-700">
<div className="flex items-center gap-3 mb-4">
<MessageSquare className="h-6 w-6 text-emerald-600 dark:text-emerald-400" />
@@ -193,7 +189,6 @@ export default function StorefrontPage() {
/>
</div>
{/* Welcome Message Section */}
<div className="bg-white dark:bg-[#0F0F12] rounded-xl shadow-lg p-6 border dark:border-zinc-700">
<div className="flex items-center gap-3 mb-4">
<MessageSquare className="h-6 w-6 text-blue-600 dark:text-blue-400" />
@@ -209,7 +204,6 @@ export default function StorefrontPage() {
/>
</div>
{/* Shipping Locations Section */}
<div className="bg-white dark:bg-[#0F0F12] rounded-xl shadow-lg p-6 border dark:border-zinc-700">
<div className="flex items-center gap-3 mb-4">
<Globe className="h-6 w-6 text-blue-600 dark:text-blue-400" />
@@ -282,7 +276,6 @@ export default function StorefrontPage() {
</div>
</div>
{/* Cryptocurrency Wallets Section */}
<div className="bg-white dark:bg-[#0F0F12] rounded-xl shadow-lg p-6 border dark:border-zinc-700">
<div className="flex items-center gap-3 mb-4">
<Wallet className="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
@@ -356,7 +349,6 @@ export default function StorefrontPage() {
</div>
</div>
{/* Action Buttons */}
<div className="flex justify-between">
<Button
onClick={() => setBroadcastOpen(true)}

View File

@@ -0,0 +1,139 @@
"use client";
import { useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Upload, AlertCircle } from "lucide-react";
import { toast } from "sonner";
import { Alert, AlertDescription } from "@/components/ui/alert";
interface ImportProductsModalProps {
open: boolean;
setOpen: (open: boolean) => void;
onImportComplete: () => void;
}
export default function ImportProductsModal({ open, setOpen, onImportComplete }: ImportProductsModalProps) {
const [file, setFile] = useState<File | null>(null);
const [isUploading, setIsUploading] = useState(false);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedFile = e.target.files?.[0];
if (selectedFile && selectedFile.type === "text/plain") {
setFile(selectedFile);
} else {
toast.error("Please select a valid .txt file");
}
};
const handleImport = async () => {
if (!file) {
toast.error("Please select a file first");
return;
}
try {
setIsUploading(true);
const fileContent = await file.text();
const products = []
const sections = fileContent.split("----------------------------------------------------------")
for (const section of sections) {
if(!section.trim()) continue
const lines = section.trim().split("\n")
const name = lines[0].trim()
const category = lines[1].trim().split("->")[0].trim()
const subcategory = lines[1].trim().split("->")[1].split("•")[0].trim()
console.log(`${name} - ${category} - ${subcategory}`)
const pricing = lines.slice(3).filter(line => line.includes('@')).map(line => {
const price = line.split('@')[0].trim()
const unit = line.split('@')[1].trim()
return { price, unit }
})
console.log(pricing)
}
//toast.success(`Successfully imported ${result.count} products`);
onImportComplete();
setOpen(false);
} catch (error) {
toast.error("Failed to import products");
console.error(error);
} finally {
setIsUploading(false);
setFile(null);
}
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Upload className="h-5 w-5" />
Import Products
</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription>
File should be a .txt file with product details in the correct format
</AlertDescription>
</Alert>
<div className="grid w-full items-center gap-1.5">
<label
htmlFor="file-upload"
className="border-2 border-dashed rounded-lg p-8 text-center cursor-pointer hover:border-gray-400 transition-colors"
>
{file ? (
<div className="text-sm text-muted-foreground">
Selected: {file.name}
</div>
) : (
<div className="text-sm text-muted-foreground">
Click to select or drag and drop a .txt file
</div>
)}
<input
id="file-upload"
type="file"
accept=".txt"
onChange={handleFileChange}
className="hidden"
/>
</label>
</div>
</div>
<DialogFooter className="sm:justify-start">
<Button
type="button"
variant="secondary"
onClick={() => setOpen(false)}
>
Cancel
</Button>
<Button
type="button"
onClick={handleImport}
disabled={!file || isUploading}
>
{isUploading ? "Importing..." : "Import Products"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}