Skip to content

Commit 18b1b10

Browse files
committed
🙅🏻‍♀️🌺 ↝ [SSM-83]: JVH Cloud generator export working, import in progress
1 parent 7522ae3 commit 18b1b10

File tree

8 files changed

+321
-43
lines changed

8 files changed

+321
-43
lines changed

components/Data/Generator/Meteorologists/JVH/cloud-classifier.tsx

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,41 @@
11
'use client'
22

3-
import { useState } from 'react'
3+
import { useState, useEffect } from 'react'
44
import { Slider } from '@/components/ui/slider'
55
import { Badge } from '@/components/ui/badge'
6-
import { CloudPattern } from '../../../../../types/Generators/JVH/atmosphere'
6+
import { CloudPattern, CloudConfiguration } from '../../../../../types/Generators/JVH/atmosphere'
77
import { cloudCompositions } from '../../../../../data/cloud-compositions'
88
import { Cloud, Wind, TornadoIcon as Hurricane, Waves, Activity } from 'lucide-react'
99
import { CloudCanvas } from './cloud-canvas'
1010
import { SciFiPanel } from '../../../../ui/styles/sci-fi/panel'
1111
import { SciFiButton } from '../../../../ui/styles/sci-fi/button'
12+
import { ConfigIOPanel } from './configuration'
1213

13-
export default function CloudClassifier() {
14+
interface CloudSignalProps {
15+
classificationConfig?: CloudConfiguration
16+
classificationId: string
17+
};
18+
19+
export default function CloudClassifier({ classificationConfig, classificationId }: CloudSignalProps) {
1420
const [selectedPatterns, setSelectedPatterns] = useState<CloudPattern[]>([])
1521
const [altitude, setAltitude] = useState(500)
1622

1723
const patterns = [
1824
{ type: 'featureless' as const, icon: <Cloud className="w-5 h-5" />, label: 'Featureless' },
1925
{ type: 'turbulent' as const, icon: <Wind className="w-5 h-5" />, label: 'Turbulent' },
2026
{ type: 'vortex' as const, icon: <Hurricane className="w-5 h-5" />, label: 'Vortex' },
21-
{ type: 'bands' as const, icon: <Waves className="w-5 h-5" />, label: 'Bands' },
22-
]
27+
{ type: 'bands' as const, icon: <Waves className="w-5 h-5" />, label: 'Bands' }
28+
];
2329

2430
const togglePattern = (pattern: CloudPattern) => {
25-
setSelectedPatterns(current =>
26-
current.includes(pattern)
27-
? current.filter(p => p !== pattern)
28-
: [...current, pattern]
29-
)
30-
}
31+
setSelectedPatterns((current) =>
32+
current.includes(pattern) ? current.filter((p) => p !== pattern) : [...current, pattern]
33+
);
34+
};
3135

3236
const getCompositionAnalysis = () => {
3337
const analysis = new Set<string>()
34-
selectedPatterns.forEach(pattern => {
38+
selectedPatterns.forEach((pattern) => {
3539
switch (pattern) {
3640
case 'featureless':
3741
analysis.add('ammonia')
@@ -54,10 +58,28 @@ export default function CloudClassifier() {
5458
return Array.from(analysis)
5559
}
5660

61+
const getCurrentConfig = (): CloudConfiguration => ({
62+
patterns: selectedPatterns,
63+
altitude,
64+
timestamp: new Date().toISOString()
65+
})
66+
67+
const handleImport = (config: CloudConfiguration) => {
68+
setSelectedPatterns(config.patterns)
69+
setAltitude(config.altitude)
70+
}
71+
72+
// Initialize the component state with classificationConfig if available
73+
useEffect(() => {
74+
if (classificationConfig) {
75+
setSelectedPatterns(classificationConfig.patterns || [])
76+
setAltitude(classificationConfig.altitude || 500)
77+
}
78+
}, [classificationConfig])
79+
5780
return (
5881
<div className="min-h-screen bg-slate-950 p-4 md:p-8 text-cyan-50">
5982
<div className="max-w-4xl mx-auto space-y-4">
60-
{/* Header */}
6183
<SciFiPanel className="p-4">
6284
<div className="flex items-center justify-between">
6385
<div>
@@ -72,7 +94,6 @@ export default function CloudClassifier() {
7294
</SciFiPanel>
7395

7496
<div className="grid md:grid-cols-2 gap-4">
75-
{/* Control Panel */}
7697
<SciFiPanel className="p-4 space-y-6">
7798
<div className="space-y-4">
7899
<h2 className="text-lg font-semibold text-cyan-400">Pattern Selection</h2>
@@ -110,7 +131,6 @@ export default function CloudClassifier() {
110131
</div>
111132
</SciFiPanel>
112133

113-
{/* Visualization Panel */}
114134
<SciFiPanel className="p-4">
115135
<h2 className="text-lg font-semibold text-cyan-400 mb-4">Cloud Formation Display</h2>
116136
<div className="h-[300px] rounded border border-cyan-500/20 overflow-hidden">
@@ -119,7 +139,12 @@ export default function CloudClassifier() {
119139
</SciFiPanel>
120140
</div>
121141

122-
{/* Analysis Panel */}
142+
<ConfigIOPanel
143+
currentConfig={getCurrentConfig()}
144+
onImport={handleImport}
145+
classificationId={classificationId}
146+
/>
147+
123148
{selectedPatterns.length > 0 && (
124149
<SciFiPanel variant="secondary" className="p-4">
125150
<h2 className="text-lg font-semibold text-red-400 mb-4">Composition Analysis</h2>
@@ -139,12 +164,12 @@ export default function CloudClassifier() {
139164
})}
140165
</div>
141166
<div className="text-sm text-red-300/70">
142-
{selectedPatterns.map(pattern => (
167+
{selectedPatterns.map((pattern) => (
143168
<p key={pattern} className="mt-1">
144-
{pattern === 'featureless' && "STATUS: Calm atmospheric region detected"}
145-
{pattern === 'turbulent' && "WARNING: Strong atmospheric activity present"}
146-
{pattern === 'vortex' && "ALERT: Deep storm system identified"}
147-
{pattern === 'bands' && "INFO: Zonal jet streams observed"}
169+
{pattern === 'featureless' && 'STATUS: Calm atmospheric region detected'}
170+
{pattern === 'turbulent' && 'WARNING: Strong atmospheric activity present'}
171+
{pattern === 'vortex' && 'ALERT: Deep storm system identified'}
172+
{pattern === 'bands' && 'INFO: Zonal jet streams observed'}
148173
</p>
149174
))}
150175
</div>
@@ -153,6 +178,5 @@ export default function CloudClassifier() {
153178
)}
154179
</div>
155180
</div>
156-
)
157-
}
158-
181+
);
182+
};
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
'use client'
2+
3+
import { useState } from 'react'
4+
import { SciFiPanel } from '@/components/ui/styles/sci-fi/panel'
5+
import { SciFiButton } from '@/components/ui/styles/sci-fi/button'
6+
import { Textarea } from '@/components/ui/textarea'
7+
import { CloudConfiguration } from '@/types/Generators/JVH/atmosphere'
8+
import { Download, Upload, AlertCircle } from 'lucide-react'
9+
import { useSupabaseClient } from '@supabase/auth-helpers-react'
10+
11+
interface ConfigIOPanelProps {
12+
currentConfig: CloudConfiguration
13+
classificationId: string
14+
onImport: (config: CloudConfiguration) => void
15+
};
16+
17+
export function ConfigIOPanel({ currentConfig, classificationId, onImport }: ConfigIOPanelProps) {
18+
const supabase = useSupabaseClient()
19+
20+
const [importText, setImportText] = useState('')
21+
const [error, setError] = useState<string | null>(null)
22+
23+
const exportConfig = () => {
24+
const configString = JSON.stringify(currentConfig, null, 2)
25+
setImportText(configString)
26+
setError(null)
27+
}
28+
29+
const [exporting, setExporting] = useState(false)
30+
31+
const handleExport = async () => {
32+
if (!classificationId) {
33+
console.error('Classification ID not found.')
34+
return
35+
}
36+
37+
setExporting(true)
38+
try {
39+
const { data, error } = await supabase
40+
.from('classifications')
41+
.select('classificationConfiguration')
42+
.eq('id', classificationId)
43+
.single()
44+
45+
if (error) throw error
46+
47+
const currentConfiguration = data?.classificationConfiguration || {}
48+
const cloudData = currentConfiguration.cloudData || {}
49+
50+
// Combine the new fields with cloudData without nested errors
51+
const updatedConfig = {
52+
...cloudData, // Keep the original cloud data
53+
patterns: currentConfig.patterns || [], // Add patterns
54+
altitude: currentConfig.altitude || 500, // Add altitude
55+
timestamp: currentConfig.timestamp || new Date().toISOString(), // Add timestamp
56+
}
57+
58+
const { error: updateError } = await supabase
59+
.from('classifications')
60+
.update({
61+
classificationConfiguration: updatedConfig
62+
})
63+
.eq('id', classificationId)
64+
65+
if (updateError) throw updateError
66+
67+
alert('Cloud data exported successfully!')
68+
} catch (err) {
69+
console.error('Error exporting cloud data:', err)
70+
alert('Failed to export cloud data.')
71+
} finally {
72+
setExporting(false)
73+
}
74+
75+
const configString = JSON.stringify(currentConfig, null, 2)
76+
setImportText(configString)
77+
setError(null)
78+
}
79+
80+
const importConfig = () => {
81+
try {
82+
const config = JSON.parse(importText) as CloudConfiguration
83+
84+
if (!config.patterns || !Array.isArray(config.patterns)) {
85+
throw new Error('Invalid patterns configuration')
86+
}
87+
if (typeof config.altitude !== 'number' || config.altitude < 0 || config.altitude > 1000) {
88+
throw new Error('Invalid altitude value')
89+
}
90+
if (!config.timestamp) {
91+
throw new Error('Missing timestamp')
92+
}
93+
94+
onImport(config)
95+
setError(null)
96+
} catch (err) {
97+
setError('Invalid configuration format')
98+
}
99+
}
100+
101+
return (
102+
<SciFiPanel className="p-4">
103+
<div className="space-y-4">
104+
<div className="flex items-center justify-between">
105+
<h2 className="text-lg font-semibold text-cyan-400">Configuration Transfer</h2>
106+
<div className="flex gap-2">
107+
<SciFiButton onClick={handleExport} className="flex items-center gap-2">
108+
<Download className="w-4 h-4" />
109+
Export
110+
</SciFiButton>
111+
<SciFiButton
112+
onClick={importConfig}
113+
variant="secondary"
114+
className="flex items-center gap-2"
115+
>
116+
<Upload className="w-4 h-4" />
117+
Import
118+
</SciFiButton>
119+
</div>
120+
</div>
121+
122+
<div>
123+
<h3 className="text-sm text-cyan-300/70">Current Configuration</h3>
124+
<pre className="font-mono text-sm bg-slate-900 text-cyan-50 p-4 rounded">
125+
{JSON.stringify(currentConfig, null, 2)}
126+
</pre>
127+
</div>
128+
129+
<Textarea
130+
value={importText}
131+
onChange={(e) => setImportText(e.target.value)}
132+
placeholder="Paste configuration data here..."
133+
className="font-mono text-sm h-32 bg-slate-900 border-cyan-500/20 text-cyan-50 placeholder:text-cyan-500/50"
134+
/>
135+
136+
{error && (
137+
<div className="flex items-center gap-2 text-red-400 text-sm">
138+
<AlertCircle className="w-4 h-4" />
139+
<span>{error}</span>
140+
</div>
141+
)}
142+
</div>
143+
</SciFiPanel>
144+
);
145+
};

components/Structures/Missions/Meteorologists/Cloudspotting/CloudMaker.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,6 @@
33
import React, { useEffect, useState } from "react";
44
import { PostCardSingleWithGenerator } from "@/content/Posts/PostWithGen";
55
import { useSession, useSupabaseClient } from "@supabase/auth-helpers-react";
6-
import CloudSignal from "./CloudSignal";
7-
8-
interface Classification {
9-
id: number;
10-
created_at: string;
11-
content: string | null;
12-
author: string | null;
13-
anomaly: number | null;
14-
media: any | null;
15-
classificationtype: string | null;
16-
classificationConfiguration: any | null;
17-
};
186

197
export default function CloudClassificationGenerator() {
208
const supabase = useSupabaseClient();
@@ -29,7 +17,7 @@ export default function CloudClassificationGenerator() {
2917
setError('User session not found.');
3018
setLoading(false);
3119
return;
32-
}
20+
};
3321

3422
setLoading(true);
3523
setError(null);

components/Structures/Missions/Meteorologists/Cloudspotting/CloudSignal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export default function CloudSignal({ classificationConfig, classificationId }:
151151
if (!classificationId) {
152152
console.error("Classification ID is missing.");
153153
return;
154-
}
154+
};
155155
setExporting(true);
156156

157157
try {

0 commit comments

Comments
 (0)