| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- "use client";
- import { useState, useEffect, useCallback } from "react";
- import {
- FileText,
- Fuel,
- Upload,
- Database,
- CheckCircle,
- Loader2,
- History,
- PlusCircle,
- } from "lucide-react";
- import {
- Card,
- CardContent,
- CardDescription,
- CardHeader,
- CardTitle,
- } from "@/components/ui/card";
- import { Button } from "@/components/ui/button";
- import { UploadForm } from "@/app/components/uploadForm";
- import {
- createTerraTechImportRecord,
- processTerraTechImportData,
- } from "@/app/actions/terratech-workflow";
- import { getImportsByLayoutName } from "@/app/actions/imports";
- import { TerraTechImportsTable } from "@/app/components/terratech/TerraTechImportsTable";
- import { TerraTechSummaryDialog } from "@/app/components/terratech/TerraTechSummaryDialog";
- import { useToast } from "@/hooks/use-toast";
- interface FileData {
- id: string;
- filename: string;
- mimetype: string;
- size: number;
- createdAt: string;
- updatedAt: string;
- }
- interface Import {
- id: number;
- name: string;
- importDate: string;
- layoutId: number;
- layout: {
- id: number;
- name: string;
- };
- }
- interface RawImportData {
- id: number;
- name: string;
- importDate: Date | string;
- layoutId: number;
- layout: {
- id: number;
- name: string;
- };
- }
- const LAYOUT_NAME = "TerraTech - GasOilWater Summary";
- export default function TerraTechFacilitySummariesPage() {
- const [imports, setImports] = useState<Import[]>([]);
- const [loading, setLoading] = useState(true);
- const [summaryDialogOpen, setSummaryDialogOpen] = useState(false);
- const [selectedImportId, setSelectedImportId] = useState<number | null>(null);
- const { toast } = useToast();
- // Workflow state
- const [viewMode, setViewMode] = useState<"imports" | "new-import">("imports");
- const [currentStep, setCurrentStep] = useState(1);
- const [uploadedFile, setUploadedFile] = useState<FileData | null>(null);
- const [isProcessing, setIsProcessing] = useState(false);
- const [importRecord, setImportRecord] = useState<Import | null>(null);
- const [error, setError] = useState<string | null>(null);
- const loadImports = useCallback(async () => {
- try {
- setLoading(true);
- setError(null);
- const result = await getImportsByLayoutName(LAYOUT_NAME);
- if (result.success && result.data) {
- const transformedImports = result.data.map((item: RawImportData) => ({
- id: item.id,
- name: item.name,
- importDate:
- item.importDate instanceof Date
- ? item.importDate.toISOString()
- : String(item.importDate),
- layoutId: item.layoutId,
- layout: {
- id: item.layout.id,
- name: item.layout.name,
- },
- }));
- setImports(transformedImports);
- } else {
- toast({
- title: "Error",
- description: result.error || "Failed to load imports",
- variant: "destructive",
- });
- setImports([]);
- }
- } catch {
- toast({
- title: "Error",
- description: "Failed to load imports",
- variant: "destructive",
- });
- } finally {
- setLoading(false);
- }
- }, [toast]);
- useEffect(() => {
- loadImports();
- }, [loadImports]);
- // Workflow handlers
- const handleFileUploaded = (file: FileData) => {
- setUploadedFile(file);
- setCurrentStep(2);
- setError(null);
- };
- const handleCreateImportRecord = async () => {
- if (!uploadedFile) return;
- setIsProcessing(true);
- setError(null);
- try {
- const result = await createTerraTechImportRecord(
- uploadedFile.id,
- uploadedFile.filename,
- );
- if (result.success && result.data) {
- const importData = result.data;
- const importRecordData: Import = {
- id: importData.id,
- name: importData.name,
- importDate:
- importData.importDate instanceof Date
- ? importData.importDate.toISOString()
- : String(importData.importDate),
- layoutId: importData.layoutId,
- layout: {
- id: importData.layout?.id || 0,
- name: importData.layout?.name || LAYOUT_NAME,
- },
- };
- setImportRecord(importRecordData);
- setCurrentStep(3);
- } else {
- setError(result.error || "Failed to create import record");
- }
- } catch (err) {
- setError(err instanceof Error ? err.message : "Unknown error occurred");
- } finally {
- setIsProcessing(false);
- }
- };
- const handleProcessImportData = async () => {
- if (!importRecord) return;
- setIsProcessing(true);
- setError(null);
- try {
- const result = await processTerraTechImportData(importRecord.id);
- if (result.success) {
- // After processing, go back to imports view
- handleBackToImports();
- } else {
- setError(result.error || "Failed to process import data");
- }
- } catch (err) {
- setError(err instanceof Error ? err.message : "Unknown error occurred");
- } finally {
- setIsProcessing(false);
- }
- };
- const handleStartNewImport = () => {
- setViewMode("new-import");
- setCurrentStep(1);
- setUploadedFile(null);
- setImportRecord(null);
- setError(null);
- };
- const handleBackToImports = () => {
- if (viewMode !== "imports") {
- setViewMode("imports");
- }
- };
- function handleViewSummary(importRecord: Import) {
- setSelectedImportId(importRecord.id);
- setSummaryDialogOpen(true);
- }
- if (loading && viewMode === "imports") {
- return (
- <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
- <div className="container mx-auto px-4 py-8">
- <div className="flex justify-center">
- <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
- </div>
- </div>
- </div>
- );
- }
- return (
- <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
- <div className="container mx-auto px-4 py-8">
- <div className="flex justify-between items-center mb-8">
- <div className="flex items-center gap-4">
- <div className="bg-amber-500 w-12 h-12 rounded-full flex items-center justify-center text-white">
- <Fuel className="w-6 h-6" />
- </div>
- <div>
- <h1 className="text-3xl font-bold text-gray-900 dark:text-white">
- TerraTech Facility Summaries
- </h1>
- <p className="text-gray-600 dark:text-gray-300">
- View Gas, Oil, and Water production summaries for imported data
- </p>
- </div>
- </div>
- </div>
- {error && (
- <div className="mb-4 p-4 bg-red-50 border border-red-200 rounded-lg">
- <p className="text-sm text-red-800">{error}</p>
- </div>
- )}
- {/* Navigation Buttons */}
- <div className="mb-6 flex gap-4">
- <Button
- variant={viewMode === "imports" ? "default" : "outline"}
- onClick={handleBackToImports}
- className="flex items-center gap-2"
- >
- <History className="h-4 w-4" />
- Prior Imports
- </Button>
- <Button
- variant={viewMode === "new-import" ? "default" : "outline"}
- onClick={handleStartNewImport}
- className="flex items-center gap-2"
- >
- <PlusCircle className="h-4 w-4" />
- New Import
- </Button>
- </div>
- {/* Table Header with Refresh Button */}
- {viewMode === "imports" && (
- <div className="flex justify-between items-center mb-4">
- <h2 className="text-xl font-semibold text-gray-900 dark:text-white">
- TerraTech Imports
- </h2>
- <Button
- onClick={loadImports}
- disabled={loading}
- variant="outline"
- size="sm"
- className="flex items-center gap-2"
- title="Refresh imports"
- >
- <Loader2
- className={`h-4 w-4 mr-2 ${loading ? "animate-spin" : ""}`}
- />
- Refresh
- </Button>
- </div>
- )}
- {/* Prior Imports View */}
- {viewMode === "imports" && (
- <>
- {imports.length === 0 ? (
- <Card className="dark:bg-gray-800 dark:border-gray-700">
- <CardContent className="flex flex-col items-center justify-center py-12">
- <FileText className="h-12 w-12 text-muted-foreground mb-4" />
- <h3 className="text-lg font-semibold mb-2 text-gray-900 dark:text-white">
- No imports found
- </h3>
- <p className="text-muted-foreground mb-4 dark:text-gray-300 text-center">
- No imports using the "{LAYOUT_NAME}" layout
- configuration were found.
- <br />
- Import data using this layout to see it here.
- </p>
- <Button onClick={handleStartNewImport}>
- Create First Import
- </Button>
- </CardContent>
- </Card>
- ) : (
- <div className="w-full">
- <TerraTechImportsTable
- data={imports}
- onViewSummary={handleViewSummary}
- />
- </div>
- )}
- </>
- )}
- {/* New Import Workflow */}
- {viewMode === "new-import" && (
- <div className="space-y-6">
- {/* Workflow Steps */}
- <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
- {[
- {
- id: 1,
- title: "Upload Excel File",
- description: "Upload the TerraTech GasOilWater Excel file",
- icon: Upload,
- status:
- currentStep >= 1
- ? uploadedFile
- ? "completed"
- : "pending"
- : "pending",
- },
- {
- id: 2,
- title: "Create Import Record",
- description: "Create import record with layout configuration",
- icon: FileText,
- status:
- currentStep >= 2
- ? importRecord
- ? "completed"
- : "pending"
- : "disabled",
- },
- {
- id: 3,
- title: "Import Data",
- description: "Process Excel file and import data",
- icon: Database,
- status:
- currentStep > 3
- ? "completed"
- : currentStep === 3
- ? "pending"
- : "disabled",
- },
- ].map((step) => {
- const Icon = step.icon;
- const getStatusColor = (status: string) => {
- switch (status) {
- case "completed":
- return "text-green-600 bg-green-50 border-green-200";
- case "pending":
- return "text-amber-600 bg-amber-50 border-amber-200";
- case "disabled":
- return "text-gray-400 bg-gray-50 border-gray-200";
- default:
- return "text-gray-600 bg-gray-50 border-gray-200";
- }
- };
- return (
- <Card
- key={step.id}
- className={`border-2 ${getStatusColor(step.status)}`}
- >
- <CardHeader className="pb-3">
- <div className="flex items-center space-x-2">
- <Icon className="h-5 w-5" />
- <div>
- <CardTitle className="text-sm font-medium">
- Step {step.id}: {step.title}
- </CardTitle>
- </div>
- </div>
- </CardHeader>
- <CardContent>
- <CardDescription className="text-xs">
- {step.description}
- </CardDescription>
- </CardContent>
- </Card>
- );
- })}
- </div>
- {/* Step Content */}
- <div className="space-y-6">
- {currentStep === 1 && (
- <Card>
- <CardHeader>
- <CardTitle>Step 1: Upload Excel File</CardTitle>
- <CardDescription>
- Upload your TerraTech GasOilWater Excel file to begin
- processing
- </CardDescription>
- </CardHeader>
- <CardContent>
- <div className="space-y-4">
- <UploadForm onFileUploaded={handleFileUploaded} />
- {uploadedFile && (
- <div className="mt-4 p-4 bg-green-50 border border-green-200 rounded-lg">
- <div className="flex items-center space-x-2">
- <CheckCircle className="h-5 w-5 text-green-600" />
- <div>
- <p className="text-sm font-medium text-green-800">
- File uploaded successfully!
- </p>
- <p className="text-sm text-green-600">
- {uploadedFile.filename} (
- {(uploadedFile.size / 1024 / 1024).toFixed(2)}{" "}
- MB)
- </p>
- </div>
- </div>
- </div>
- )}
- </div>
- </CardContent>
- </Card>
- )}
- {currentStep === 2 && (
- <Card>
- <CardHeader>
- <CardTitle>Step 2: Create Import Record</CardTitle>
- <CardDescription>
- Creating import record with TerraTech - GasOilWater
- Summary layout configuration
- </CardDescription>
- </CardHeader>
- <CardContent>
- <div className="space-y-4">
- <p className="text-sm text-muted-foreground">
- File: {uploadedFile?.filename}
- </p>
- <p className="text-sm text-muted-foreground">
- Layout: {LAYOUT_NAME}
- </p>
- <Button
- onClick={handleCreateImportRecord}
- disabled={isProcessing}
- className="w-full bg-amber-500 hover:bg-amber-600"
- >
- {isProcessing ? (
- <>
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
- Creating Import Record...
- </>
- ) : (
- "Create Import Record"
- )}
- </Button>
- </div>
- </CardContent>
- </Card>
- )}
- {currentStep === 3 && (
- <Card>
- <CardHeader>
- <CardTitle>Step 3: Import Data</CardTitle>
- <CardDescription>
- Processing Excel file and importing data into database
- </CardDescription>
- </CardHeader>
- <CardContent>
- <div className="space-y-4">
- <p className="text-sm text-muted-foreground">
- Import ID: {importRecord?.id}
- </p>
- <p className="text-sm text-muted-foreground">
- Import Name: {importRecord?.name}
- </p>
- <Button
- onClick={handleProcessImportData}
- disabled={isProcessing}
- className="w-full bg-amber-500 hover:bg-amber-600"
- >
- {isProcessing ? (
- <>
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
- Processing Import...
- </>
- ) : (
- "Process Import"
- )}
- </Button>
- </div>
- </CardContent>
- </Card>
- )}
- </div>
- </div>
- )}
- <TerraTechSummaryDialog
- open={summaryDialogOpen}
- onOpenChange={setSummaryDialogOpen}
- importId={selectedImportId || 0}
- />
- </div>
- </div>
- );
- }
|