Добавление заметок

This commit is contained in:
test 2025-06-12 15:24:50 +05:00
parent ea56d17ea7
commit e61ffd793c
20 changed files with 274 additions and 118 deletions

View file

@ -25,8 +25,6 @@ interface ListUsersProps {
}
const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps) => {
// Фильтр по статусу
const activeDevices = devices.filter(device => device.status === 'online');
const inactiveDevices = devices.filter(device => device.status !== 'online');
@ -55,7 +53,7 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps
</div>
{/* Колонка неактивных устройств */}
<div style={{ flex: 1 }}>
<h3 style={{ color: '#F44336', marginBottom:'12px' }}>Неактивные устройства ({inactiveDevices.length})</h3>
<h3 style={{ color: '#ababab', marginBottom:'12px' }}>Неактивные устройства ({inactiveDevices.length})</h3>
{inactiveDevices.map((device, index) => (
<DeviceCard
key={index}

View file

@ -14,21 +14,21 @@ type Option ={
// Анимации
const ring1 = keyframes`
0% { width: 250px; height: 250px; }
50% { width: 280px; height: 280px; }
100% { width: 250px; height: 250px; }
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.12; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.12; }
`;
const ring2 = keyframes`
0% { width: 400px; height: 400px; }
50% { width: 430px; height: 430px; }
100% { width: 400px; height: 400px; }
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.08; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.15; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.08; }
`;
const ring3 = keyframes`
0% { width: 550px; height: 550px; }
50% { width: 580px; height: 580px; }
100% { width: 550px; height: 550px; }
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.04; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.1; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.04; }
`;
const dotAnimation = keyframes`
0% { content: '.'; }
@ -36,6 +36,11 @@ const dotAnimation = keyframes`
66% { content: '...'; }
100% { content: '.'; }
`;
const pulse = keyframes`
0% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(1.1); }
100% { transform: translate(-50%, -50%) scale(1); }
`;
// Стили
const Wrapper = styled.div<{ scanInitiated: boolean, loading: boolean}>`
@ -60,8 +65,8 @@ const TitleWrapper = styled.h2`
left: 50%;
transform: translateX(-50%);
font-size: 32px;
width: max-content;
`
const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
width: 60px;
height: 60px;
@ -77,11 +82,11 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
&.center{
&.center {
width: 60px;
height: 60px;
}
animation: ${({ loading }) => (loading ? pulse : "none")} 2s ease infinite;
}
&.ring1 {
opacity: 0.12;
width: 250px;
@ -94,6 +99,7 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
width: 400px;
height: 400px;
animation: ${({ loading }) => (loading ? ring2 : "none")} 4s linear infinite;
animation-delay: ${({ loading }) => (loading ? "0.1s" : "0")};
}
&.ring3 {
@ -101,9 +107,9 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
width: 550px;
height: 550px;
animation: ${({ loading }) => (loading ? ring3 : "none")} 4s linear infinite;
animation-delay: ${({ loading }) => (loading ? "0.2s" : "0")};
}
}
`;
const LoadingText = styled.div`

View file

@ -15,27 +15,30 @@ type Option ={
// Анимации
const ring1 = keyframes`
0% { width: 250px; height: 250px; }
50% { width: 280px; height: 280px; }
100% { width: 250px; height: 250px; }
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.12; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.12; }
`;
const ring2 = keyframes`
0% { width: 400px; height: 400px; }
50% { width: 430px; height: 430px; }
100% { width: 400px; height: 400px; }
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.08; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.15; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.08; }
`;
const ring3 = keyframes`
0% { width: 550px; height: 550px; }
50% { width: 580px; height: 580px; }
100% { width: 550px; height: 550px; }
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.04; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.1; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.04; }
`;
const dotAnimation = keyframes`
0% { content: '.'; }
33% { content: '..'; }
66% { content: '...'; }
100% { content: '.'; }
0% { content: '.'; }
33% { content: '..'; }
66% { content: '...'; }
100% { content: '.'; }
`;
const pulse = keyframes`
0% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(1.1); }
100% { transform: translate(-50%, -50%) scale(1); }
`;
// Стили
@ -43,7 +46,7 @@ const Wrapper = styled.div<{ scanInitiated: boolean, loading: boolean}>`
display: flex;
flex-direction: column;
align-items: center;
justify-content:${({scanInitiated, loading})=>(scanInitiated && !loading ? 'start' : 'center')};
justify-content:center ;
height: 100%;
width: 100%;
position: relative;
@ -68,8 +71,8 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
height: 60px;
border-radius: 50%;
position: relative;
transition: .4s ease;
transform: ${({scanInitiated,loading})=>(scanInitiated && !loading ? 'scale(0)' : 'scale(1)')};
transition: .4s ease;
transform: scale(1);
span {
position: absolute;
display: inline-block;
@ -78,11 +81,11 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
&.center{
&.center {
width: 60px;
height: 60px;
}
animation: ${({ loading }) => (loading ? pulse : "none")} 2s ease infinite;
}
&.ring1 {
opacity: 0.12;
width: 250px;
@ -95,6 +98,7 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
width: 400px;
height: 400px;
animation: ${({ loading }) => (loading ? ring2 : "none")} 4s linear infinite;
animation-delay: ${({ loading }) => (loading ? "0.1s" : "0")};
}
&.ring3 {
@ -102,11 +106,12 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
width: 550px;
height: 550px;
animation: ${({ loading }) => (loading ? ring3 : "none")} 4s linear infinite;
animation-delay: ${({ loading }) => (loading ? "0.2s" : "0")};
}
}
`;
const LoadingText = styled.div`
position: relative;
padding: 14px 22px;
@ -122,7 +127,7 @@ const ScanningText = styled.span`
animation: ${dotAnimation} 1.5s infinite;
}
`;
const ScanBtn = styled.button<{loading: boolean}>`
const ScanBtn = styled.button<{scanInitiated: boolean}>`
position: relative;
padding: 14px 22px;
background-color: #4CAF50;
@ -130,80 +135,46 @@ const ScanBtn = styled.button<{loading: boolean}>`
border: none;
border-radius: 12px;
font-size: 18px;
transition: .4s ease;
transform: ${({loading}) => (!loading ? "translateY(240px)" : "translateY(0)")};
transition: transform .4s ease;
transform: ${({scanInitiated}) => (scanInitiated ? "translateY(240px)" : "translateY(0)")};
&:hover{
transform: ${({loading}) => (!loading ? "translateY(240px)" : "translateY(0)")} scale(1.03);
transform: ${({scanInitiated}) => (scanInitiated ? "translateY(240px)" : "translateY(0)")} scale(1.03);
}
`
const data = [
{
ssid: "Huawei",
bssid: "wef",
channel: 0,
signal:2,
encryption: "wef",
frequency: "ewf",
vendor: "striwefwng",
hidden: false
},
{
ssid: "Gu-2",
bssid: "grgerger",
channel: 0,
signal: 2,
encryption: "weergref",
frequency: "eergewf",
vendor: "grgregerge",
hidden: false
},
{
ssid: "Huawei_wifi2",
bssid: "wqdqw",
channel: 2,
signal: 3,
encryption: "wefwe",
frequency: "wef",
vendor: "fwefw",
hidden: false
},
];
export function WifiScanner() {
const {ipAddress} = useIpStore();
const ipAddress = '192.168.1.147';
const [loading, setLoading] = useState(false);
const [scanInitiated, setScanInitiated] = useState(false);
const {wifiNetworks, setWifiNetworks} = useNetworkStore();
const [currentNetwork, setCurrentNetwork] = useState<WifiNetworkScanner | null>(null);
const handleScan = async () => {
try {
const handleScan = async () => {
setWifiNetworks([]);
setLoading(true);
setScanInitiated(true);
const res = await NetworkService.scanWifi(ipAddress);
const networks = res.data.access_points || [];
setWifiNetworks(networks);
} catch (err) {
console.error("Ошибка сканирования сети:", err);
setWifiNetworks([]);
} finally {
setLoading(false);
}
};
try {
const res = await NetworkService.scanWifi(ipAddress);
const networks = res.data.access_points || [];
setWifiNetworks(networks);
} catch (err) {
console.error("Ошибка сканирования сети:", err);
setWifiNetworks([]);
} finally {
setLoading(false);
}
};
return (
<Wrapper scanInitiated={scanInitiated} loading={loading}>
{(!scanInitiated || loading) && (
<TitleWrapper>Сканирование Wi-Fi сети</TitleWrapper>
)}
<TitleWrapper>Сканирование Wi-Fi сети</TitleWrapper>
<UserLocate loading={loading} scanInitiated={scanInitiated}>
<span className="center"></span>
<span className="ring1"></span>
<span className="ring2"></span>
<span className="ring3"></span>
{data.map((network) => (
{wifiNetworks.map((network) => (
<WifiDot
key={network.bssid}
network={network}
@ -224,7 +195,7 @@ export function WifiScanner() {
Сканирование сети <ScanningText/>
</LoadingText>
) : (
<ScanBtn onClick={handleScan} disabled={loading} loading={loading}>
<ScanBtn onClick={handleScan} disabled={loading} scanInitiated={scanInitiated}>
{wifiNetworks.length > 0 ? 'Обновить список' : 'Сканировать сеть'}
</ScanBtn>
)}

View file

@ -25,7 +25,7 @@ const CloseBtn = styled.div`
top: -20px;
right: -20px;
cursor: pointer;
background-color: white;
background-color: ${(props) => props.theme.primary};
border-radius: 50%;
display: flex;
justify-content: center;
@ -37,7 +37,7 @@ const CloseBtn = styled.div`
visibility: visible;
&:hover {
background-color: #d6d6d6;
background-color: ${(props) => props.theme.hoverBtn};
}
`
const ModalTitle = styled.div`
@ -100,9 +100,9 @@ const ModalWifiScaner = ({ network,onClose }: { network: WifiNetworkScanner, onC
<ModalTitle>
<h4>{network.ssid}</h4>
<SignalBarsWrapper>
<SignalBar active={network.signal >= 1} />
<SignalBar active={network.signal >= 2} />
<SignalBar active={network.signal >= 3} />
<SignalBar active={network.signal >= -120} />
<SignalBar active={network.signal >= -70} />
<SignalBar active={network.signal >= -50} />
</SignalBarsWrapper>
</ModalTitle>
<ModalContent>

View file

@ -46,15 +46,24 @@ const WifiDot = ({ network, onSelect }: { network: WifiNetworkScanner, onSelect:
};
const getPosition = (signal: number, bssid: string) => {
const strength = Math.min(3, Math.max(1, signal));
let strength: 1 | 2 | 3;
if (signal >= -50) {
strength = 3;
} else if (signal >= -70) {
strength = 2;
} else if (signal >= -90) {
strength = 1;
} else {
strength = 1;
}
const ringSizes = { 1: 550, 2: 400, 3: 250 };
const ringSize = ringSizes[strength as 1 | 2 | 3];
const ringSize = ringSizes[strength];
const offset = getPositionInRing(bssid, ringSize);
return {
top: `calc(50% - ${offset.y}px)`,
left: `calc(50% - ${offset.x}px)`
}
};
};
const position = getPosition(network.signal, network.bssid);

View file

@ -57,7 +57,7 @@ export const ToolBar = () => {
</Button>
<Button>
<IconContainer>
<IconComponent name={buttonNames[14]} width="30" height="30" onClick={() => setWorkModule(workSpaceNames[6])} />
<IconComponent name={buttonNames[15]} width="30" height="30" onClick={() => setWorkModule(workSpaceNames[6])} />
</IconContainer>
</Button>
</ButtonContainer>