|
1 | 1 | import React, { useState } from 'react';
|
2 | 2 | import {
|
3 |
| - Button, ColorInput, Fieldset, Modal, Text, |
| 3 | + Accordion, |
| 4 | + ActionIcon, |
| 5 | + Button, Center, ColorInput, Fieldset, FocusTrap, Group, LoadingOverlay, Modal, Text, |
| 6 | + TextInput, ThemeIcon, Tooltip, |
4 | 7 | } from '@mantine/core';
|
5 | 8 | import { useDisclosure } from '@mantine/hooks';
|
| 9 | +import { notifications } from '@mantine/notifications'; |
| 10 | +import { IconCheck, IconCopy, IconX } from '@tabler/icons-react'; |
6 | 11 | import { convertToChinese, convertToColor } from '../utils';
|
7 | 12 |
|
| 13 | +export function BalloonsClient({ clients, refresh }) { |
| 14 | + const [adding, setAdding] = useState(false); |
| 15 | + const [opened, { open, close }] = useDisclosure(false); |
| 16 | + const [name, setName] = useState(''); |
| 17 | + |
| 18 | + const addClient = async () => { |
| 19 | + setAdding(true); |
| 20 | + try { |
| 21 | + const res = await (await fetch('/client', { |
| 22 | + method: 'POST', |
| 23 | + headers: { 'Content-Type': 'application/json' }, |
| 24 | + body: JSON.stringify({ name, operation: 'add', type: 'balloon' }), |
| 25 | + })).json(); |
| 26 | + if (res.error) { |
| 27 | + notifications.show({ title: 'Error', message: `${res.error.message}(${res.error.params})`, color: 'red' }); |
| 28 | + setAdding(false); |
| 29 | + return; |
| 30 | + } |
| 31 | + notifications.show({ title: 'Success', message: 'Client added', color: 'green' }); |
| 32 | + setName(''); |
| 33 | + } catch (e) { |
| 34 | + console.error(e); |
| 35 | + notifications.show({ title: 'Error', message: 'Failed to add client', color: 'red' }); |
| 36 | + } |
| 37 | + setAdding(false); |
| 38 | + close(); |
| 39 | + refresh(); |
| 40 | + }; |
| 41 | + return ( |
| 42 | + <> |
| 43 | + <Modal |
| 44 | + opened={opened} |
| 45 | + onClose={() => { close(); setName(''); }} |
| 46 | + title="Clients" |
| 47 | + size="md" |
| 48 | + padding="md" |
| 49 | + > |
| 50 | + <Fieldset legend="Add Client" mb="lg"> |
| 51 | + <LoadingOverlay visible={adding} zIndex={1000} overlayProps={{ radius: 'sm', blur: 2 }} /> |
| 52 | + <FocusTrap active> |
| 53 | + <TextInput label="Client Name" placeholder="Client Name" value={name} onChange={(e) => setName(e.currentTarget.value)} data-autofocus /> |
| 54 | + </FocusTrap> |
| 55 | + <Button color="blue" fullWidth mt="md" radius="md" onClick={addClient}>Submit</Button> |
| 56 | + </Fieldset> |
| 57 | + <Fieldset legend="Clients" mb="lg"> |
| 58 | + <Accordion> |
| 59 | + {clients.map((item) => ( |
| 60 | + <Accordion.Item key={item.id} value={item.name}> |
| 61 | + <Accordion.Control |
| 62 | + icon={(<Tooltip label={item.updateAt && item.updateAt > new Date().getTime() - 1000 * 60 ? 'Online' : 'Offline'}> |
| 63 | + <ThemeIcon radius="xl" size="sm" color={item.updateAt ? 'green' : 'red'}> |
| 64 | + { item.updateAt ? (<IconCheck />) : (<IconX />)} |
| 65 | + </ThemeIcon> |
| 66 | + </Tooltip>)} |
| 67 | + > |
| 68 | + <Tooltip label={`${item.name}(${item.id})`}> |
| 69 | + <Text>{item.name}({item.id})</Text> |
| 70 | + </Tooltip> |
| 71 | + </Accordion.Control> |
| 72 | + <Accordion.Panel> |
| 73 | + <Group justify="center" gap="md"> |
| 74 | + <Text>ID: {item.id}</Text> |
| 75 | + <Tooltip label="Copy ID"> |
| 76 | + <ActionIcon variant="transparent" color="blue" aria-label='Copy ID' ml="xs" onClick={() => { |
| 77 | + notifications.show({ title: 'Success', message: 'ID Copied to clipboard!', color: 'green' }); |
| 78 | + }}><IconCopy /></ActionIcon> |
| 79 | + </Tooltip> |
| 80 | + </Group> |
| 81 | + { !item.updateAt ? ( |
| 82 | + <Center mt="md"> |
| 83 | + <Text c="dimmed">Have not connected yet</Text> |
| 84 | + </Center> |
| 85 | + ) : ( |
| 86 | + <> |
| 87 | + <Text>IP: {item.ip}</Text> |
| 88 | + <Text>Updated At: {new Date(item.updateAt).toLocaleString()}</Text> |
| 89 | + </> |
| 90 | + )} |
| 91 | + </Accordion.Panel> |
| 92 | + </Accordion.Item> |
| 93 | + ))} |
| 94 | + </Accordion> |
| 95 | + </Fieldset> |
| 96 | + </Modal> |
| 97 | + <Button color="blue" radius="md" onClick={open}>Client Info</Button> |
| 98 | + </> |
| 99 | + ); |
| 100 | +} |
| 101 | + |
8 | 102 | export function BallonColorChecker() {
|
9 | 103 | const [opened, { open, close }] = useDisclosure(false);
|
10 | 104 | const [value, setValue] = useState('');
|
|
0 commit comments