Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
parkpow
GitHub Repository: parkpow/deep-license-plate-recognition
Path: blob/master/gate-controller/components/ApiInstructionsModal.tsx
1082 views
1
'use client';
2
3
import { useState, useEffect } from 'react';
4
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
5
import { Button } from '@/components/ui/button';
6
import { toast } from 'sonner';
7
import { ClipboardCopy } from 'lucide-react';
8
import { invoke } from '@tauri-apps/api/core';
9
10
interface Relay {
11
id: string;
12
type: 'ch340' | 'hw348' | 'cp210x';
13
channels?: number;
14
}
15
16
interface ApiInstructionsModalProps {
17
relay: Relay;
18
isOpen: boolean;
19
onClose: () => void;
20
}
21
22
const CodeBlock = ({ payload }: { payload: object }) => {
23
const payloadString = JSON.stringify(payload, null, 2);
24
25
const handleCopy = () => {
26
navigator.clipboard.writeText(payloadString);
27
toast.success('Payload copied to clipboard!');
28
};
29
30
return (
31
<div className="relative bg-gray-900 text-white rounded-md p-4 font-mono text-sm my-2">
32
<Button variant="ghost" size="icon" className="absolute top-2 right-2 h-8 w-8" onClick={handleCopy}>
33
<ClipboardCopy className="h-4 w-4" />
34
</Button>
35
<pre><code>{payloadString}</code></pre>
36
</div>
37
);
38
};
39
40
export function ApiInstructionsModal({ relay, isOpen, onClose }: ApiInstructionsModalProps) {
41
const [webhookUrl, setWebhookUrl] = useState('');
42
const isMultiChannel = relay.type === 'ch340' || relay.type === 'hw348' || relay.type === 'cp210x';
43
44
useEffect(() => {
45
async function getToken() {
46
try {
47
const token = await invoke('get_webhook_token');
48
// Assuming the server runs on localhost:4848
49
// This could be made configurable in the future
50
setWebhookUrl(`http://localhost:4848/webhook/${token}`);
51
} catch (error) {
52
console.error("Failed to get webhook token:", error);
53
setWebhookUrl('Could not retrieve webhook URL.');
54
}
55
}
56
if (isOpen) {
57
getToken();
58
}
59
}, [isOpen]);
60
61
return (
62
<Dialog open={isOpen} onOpenChange={onClose}>
63
<DialogContent className="max-w-lg">
64
<DialogHeader>
65
<DialogTitle className="text-lg">API Instructions for {relay.id}</DialogTitle>
66
</DialogHeader>
67
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 mt-2">
68
<div className="md:col-span-2">
69
<h3 className="font-semibold text-sm">Payloads</h3>
70
<p className="text-xs text-gray-500 mb-1">The body of your POST request must be a JSON object with one of the following structures.</p>
71
72
<h4 className="font-medium text-sm">Standard Actions</h4>
73
<div className="grid grid-cols-1 md:grid-cols-2 gap-1">
74
<CodeBlock payload={{ id: relay.id, action: 'on', ...(isMultiChannel && { channel: 1 }) }} />
75
<CodeBlock payload={{ id: relay.id, action: 'off', ...(isMultiChannel && { channel: 1 }) }} />
76
</div>
77
78
<h4 className="font-medium text-sm mt-2">Toggle Actions</h4>
79
<p className="text-xs text-gray-500 mb-1">
80
The <code>toggle</code> parameter inverts the action after a <code>period</code> (in milliseconds).
81
</p>
82
<div className="grid grid-cols-1 md:grid-cols-2 gap-1">
83
<CodeBlock payload={{ id: relay.id, action: 'on', toggle: true, period: 5000, ...(isMultiChannel && { channel: 1 }) }} />
84
<CodeBlock payload={{ id: relay.id, action: 'off', toggle: true, period: 5000, ...(isMultiChannel && { channel: 1 }) }} />
85
</div>
86
87
{isMultiChannel && relay.channels && relay.channels > 1 && (
88
<p className="text-xs text-gray-500 mt-1">For this relay, you can change the <code>channel</code> value from 1 to {relay.channels}.</p>
89
)}
90
</div>
91
</div>
92
</DialogContent>
93
</Dialog>
94
);
95
}
96
97