+
@@ -539,12 +539,12 @@ export default function EquipmentPage() {
{/* Название */}
-
+
setForm((p) => ({ ...p, name: e.target.value }))}
placeholder="Ноутбук Lenovo ThinkPad X1..."
- className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-100"
+ className="app-input w-full rounded-lg px-3 py-2 text-sm"
/>
@@ -558,8 +558,8 @@ export default function EquipmentPage() {
/>
{isCreateMode && previewInventoryNumber && (
-
- Следующий инвентарный номер:
{previewInventoryNumber}
+
+ Следующий инвентарный номер: {previewInventoryNumber}
)}
@@ -585,14 +585,14 @@ export default function EquipmentPage() {
{modalMode === "create" && (
-
+
setForm((p) => ({ ...p, quantity: Math.max(1, Math.min(100, Number(e.target.value) || 1)) }))}
- className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-100"
+ className="app-input w-full rounded-lg px-3 py-2 text-sm"
/>
)}
@@ -600,58 +600,58 @@ export default function EquipmentPage() {
{/* Дата покупки + стоимость */}
{/* Серийный номер */}
-
+
setForm((p) => ({ ...p, serial_number: e.target.value }))}
placeholder="SN-XXXXX"
- className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-100"
+ className="app-input w-full rounded-lg px-3 py-2 text-sm"
/>
{/* Расположение */}
-
+
setForm((p) => ({ ...p, location: e.target.value }))}
placeholder="Офис 305, стол 2..."
- className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-100"
+ className="app-input w-full rounded-lg px-3 py-2 text-sm"
/>
{/* Заметки */}
-
+
@@ -663,10 +663,10 @@ export default function EquipmentPage() {
"Добавить обслуживание"
} size="md" footer={
-
- {operationModal === "transfer" && }
+
+ {operationModal === "transfer" && }
{operationModal === "writeoff" && }
- {operationModal === "maintenance" && }
+ {operationModal === "maintenance" && }
}>
{operationModal === "transfer" && (
@@ -686,24 +686,24 @@ export default function EquipmentPage() {
onSelect={(id) => setTransferForm((prev) => ({ ...prev, to_person: id }))}
/>
-
-
)}
{operationModal === "writeoff" && (
-
-
)}
{operationModal === "maintenance" && (
-
-
-
- setMaintenanceForm((prev) => ({ ...prev, description: e.target.value }))} rows={4} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-100" />
+
+ setMaintenanceForm((prev) => ({ ...prev, description: e.target.value }))} rows={4} className="app-input w-full rounded-lg px-3 py-2 text-sm" />
)}
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index 60333106..fd81b8a0 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -124,6 +124,11 @@ textarea {
border: 1px solid var(--border-strong);
color: var(--foreground);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
+ transition:
+ background-color 160ms ease,
+ border-color 160ms ease,
+ box-shadow 160ms ease,
+ color 160ms ease;
}
.app-field-label {
@@ -169,6 +174,11 @@ textarea {
background: var(--surface-secondary);
cursor: pointer;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
+ transition:
+ background-color 160ms ease,
+ border-color 160ms ease,
+ box-shadow 160ms ease,
+ transform 160ms ease;
}
.app-color-input::-webkit-color-swatch-wrapper {
@@ -184,6 +194,13 @@ textarea {
color: var(--muted-foreground);
}
+.app-input:hover,
+.app-select:hover,
+.app-color-input:hover {
+ background: var(--surface-tertiary);
+ border-color: color-mix(in srgb, var(--accent-primary) 22%, var(--border-strong));
+}
+
.app-input:focus,
.app-select:focus {
background: var(--surface-elevated);
@@ -192,6 +209,12 @@ textarea {
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-primary) 18%, transparent);
}
+.app-color-input:focus {
+ border-color: var(--accent-primary);
+ outline: none;
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-primary) 18%, transparent);
+}
+
.app-input[type="date"],
.app-input[type="datetime-local"],
.app-input[type="time"] {
diff --git a/frontend/src/app/messages/page.tsx b/frontend/src/app/messages/page.tsx
index 3cb51c5b..3a1f9efd 100644
--- a/frontend/src/app/messages/page.tsx
+++ b/frontend/src/app/messages/page.tsx
@@ -610,7 +610,7 @@ export default function MessagesPage() {
value={newChatName}
onChange={(e) => setNewChatName(e.target.value)}
placeholder="Введите название чата..."
- className="app-input w-full rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-sky-100"
+ className="app-input w-full rounded-lg px-3 py-2 text-sm"
/>
@@ -622,7 +622,7 @@ export default function MessagesPage() {
onChange={(e) => setNewChatDescription(e.target.value)}
placeholder="Краткое описание чата..."
rows={3}
- className="app-input w-full rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-sky-100"
+ className="app-input w-full rounded-lg px-3 py-2 text-sm"
/>
diff --git a/frontend/src/app/notifications/page.tsx b/frontend/src/app/notifications/page.tsx
index 67ef2287..665a3d76 100644
--- a/frontend/src/app/notifications/page.tsx
+++ b/frontend/src/app/notifications/page.tsx
@@ -2,12 +2,11 @@
import { AppShell } from '@/components/AppShell';
import { apiClient } from '@/lib/api';
-import { Bell, Check, CheckCheck, Filter, Search, Trash2, Settings } from 'lucide-react';
+import { Bell, CheckCheck, Filter, Search, Trash2 } from 'lucide-react';
import { useState, useMemo, useEffect } from 'react';
import { formatDistanceToNow } from 'date-fns';
import { ru } from 'date-fns/locale/ru';
import { getVerbCategory, getVerbName } from '@/lib/verbTranslations';
-import Link from 'next/link';
export default function NotificationsPage() {
// Локальное состояние для ВСЕХ уведомлений (не только непрочитанных)
@@ -165,20 +164,15 @@ export default function NotificationsPage() {
return (