fix import with name "viplight"
This commit is contained in:
@@ -7,7 +7,7 @@ import (
|
|||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"viplight-mrp/models"
|
"mrp/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DB *gorm.DB
|
var DB *gorm.DB
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"viplight-mrp/database"
|
"mrp/database"
|
||||||
"viplight-mrp/models"
|
"mrp/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetsOrders(c *gin.Context) {
|
func GetsOrders(c *gin.Context) {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"viplight-mrp/database"
|
"mrp/database"
|
||||||
"viplight-mrp/models"
|
"mrp/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPart(c *gin.Context) {
|
func GetPart(c *gin.Context) {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
"viplight-mrp/database"
|
"mrp/database"
|
||||||
"viplight-mrp/models"
|
"mrp/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Login(c *gin.Context) {
|
func Login(c *gin.Context) {
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,7 @@ services:
|
|||||||
container_name: mrp_db
|
container_name: mrp_db
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "5433:5433"
|
- "5433:5432"
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: ${DB_USER}
|
POSTGRES_USER: ${DB_USER}
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
@@ -40,3 +40,5 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pg_data:
|
pg_data:
|
||||||
|
external: true
|
||||||
|
name: viplight_mrp_pg_data
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import PartDetail from "./pages/PartDetail";
|
|||||||
import AddPartPage from "./pages/AddPartPage";
|
import AddPartPage from "./pages/AddPartPage";
|
||||||
import ProfilePage from "./pages/ProfilePage";
|
import ProfilePage from "./pages/ProfilePage";
|
||||||
import AuthForm from "./components/AuthForm";
|
import AuthForm from "./components/AuthForm";
|
||||||
import RegisterForm from "./components/RegisterForm";
|
|
||||||
|
|
||||||
const PrivateRoute = ({ children }) => {
|
const PrivateRoute = ({ children }) => {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const AuthForm = () => {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setMessage({
|
setMessage({
|
||||||
text: err.response?.data?.error || "Неверный логин или пароль",
|
text: err.response?.data?.error || err.message || "Неверный логин или пароль",
|
||||||
isError: true,
|
isError: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,27 +21,11 @@ export default function Header({ onRefresh, onOpenScanner }) {
|
|||||||
<div className="max-w-[1440px] mx-auto px-4 md:px-8 h-16 md:h-20 flex justify-between items-center">
|
<div className="max-w-[1440px] mx-auto px-4 md:px-8 h-16 md:h-20 flex justify-between items-center">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="text-lg md:text-xl font-black text-white tracking-tighter">
|
<h1 className="text-lg md:text-xl font-black text-white tracking-tighter">
|
||||||
VIPLIGHT <span className="text-blue-500">MRP</span>
|
<span className="text-blue-500">MRP</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="hidden md:block">
|
|
||||||
<CsvImporter onImported={onRefresh} />
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
onClick={() => navigate("/add")}
|
|
||||||
className="hidden md:flex h-10 px-6 bg-emerald-600 hover:bg-emerald-500 text-white rounded-xl font-bold text-xs items-center gap-2"
|
|
||||||
>
|
|
||||||
<span>+</span> НОВАЯ ПАНЕЛЬ
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={onOpenScanner}
|
|
||||||
className="h-9 px-4 md:h-10 md:px-6 bg-blue-600 hover:bg-blue-500 text-white rounded-lg md:rounded-xl font-bold text-xs flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<span>📷</span> СКАНЕР
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Блок пользователя */}
|
{/* Блок пользователя */}
|
||||||
<div
|
<div
|
||||||
onClick={() => navigate("/profile")}
|
onClick={() => navigate("/profile")}
|
||||||
@@ -49,11 +33,8 @@ export default function Header({ onRefresh, onOpenScanner }) {
|
|||||||
>
|
>
|
||||||
<div className="text-right hidden sm:block">
|
<div className="text-right hidden sm:block">
|
||||||
<p className="text-sm font-bold text-white leading-tight">
|
<p className="text-sm font-bold text-white leading-tight">
|
||||||
{user.first_name} {user.last_name}
|
{"Привет, "}
|
||||||
</p>
|
{user.first_name}
|
||||||
<p className="text-[10px] text-slate-400 font-medium uppercase tracking-widest mt-0.5">
|
|
||||||
{user.department} <span className="text-slate-600 mx-1">|</span>{" "}
|
|
||||||
{user.role}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { registerUser } from "../api"; // Используем твой метод из index.js
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export default function RegisterForm() {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
username: "",
|
|
||||||
password: "",
|
|
||||||
first_name: "",
|
|
||||||
last_name: "",
|
|
||||||
phone: "",
|
|
||||||
department: "",
|
|
||||||
role: "Рабочий",
|
|
||||||
});
|
|
||||||
const [message, setMessage] = useState({ text: "", isError: false });
|
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setMessage({ text: "", isError: false });
|
|
||||||
|
|
||||||
try {
|
|
||||||
await registerUser(formData);
|
|
||||||
setMessage({ text: "Сотрудник успешно создан!", isError: false });
|
|
||||||
// Небольшая задержка перед переходом, чтобы админ увидел успех
|
|
||||||
setTimeout(() => navigate("/"), 1500);
|
|
||||||
} catch (err) {
|
|
||||||
setMessage({
|
|
||||||
text: err.response?.data?.error || "Ошибка регистрации",
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen flex items-center justify-center bg-slate-950 px-4 py-10">
|
|
||||||
<div className="w-full max-w-lg space-y-8 bg-slate-900 p-10 rounded-2xl border border-slate-800 shadow-2xl">
|
|
||||||
<div className="text-center">
|
|
||||||
<h2 className="text-3xl font-black text-white tracking-tighter">
|
|
||||||
VIPLIGHT <span className="text-blue-500">MRP</span>
|
|
||||||
</h2>
|
|
||||||
<p className="mt-2 text-sm text-slate-400 uppercase tracking-widest">
|
|
||||||
Регистрация сотрудника
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form className="mt-8 space-y-4" onSubmit={handleSubmit}>
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white placeholder-slate-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
||||||
placeholder="Имя"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, first_name: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white placeholder-slate-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
||||||
placeholder="Фамилия"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, last_name: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
required
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white placeholder-slate-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
||||||
placeholder="Email (Логин)"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, username: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
required
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white placeholder-slate-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
||||||
placeholder="Пароль (мин. 8 символов)"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, password: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white placeholder-slate-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
||||||
placeholder="Телефон"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, phone: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white placeholder-slate-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
||||||
placeholder="Отдел"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, department: e.target.value })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<select
|
|
||||||
className="appearance-none block w-full px-3 py-3 border border-slate-800 bg-slate-800 text-white rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm cursor-pointer"
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({ ...formData, role: e.target.value })
|
|
||||||
}
|
|
||||||
value={formData.role}
|
|
||||||
>
|
|
||||||
<option value="Рабочий">Рабочий</option>
|
|
||||||
<option value="Менеджер">Менеджер</option>
|
|
||||||
<option value="Админ">Админ</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{message.text && (
|
|
||||||
<p
|
|
||||||
className={`text-center text-xs font-bold uppercase tracking-tighter ${message.isError ? "text-red-500" : "text-emerald-500"}`}
|
|
||||||
>
|
|
||||||
{message.text}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex gap-4 pt-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => navigate("/")}
|
|
||||||
className="w-1/3 py-3 px-4 border border-slate-800 text-sm font-bold rounded-xl text-slate-400 hover:bg-slate-800 transition-all"
|
|
||||||
>
|
|
||||||
ОТМЕНА
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="w-2/3 py-3 px-4 border border-transparent text-sm font-bold rounded-xl text-white bg-blue-600 hover:bg-blue-500 transition-all active:scale-95 shadow-lg shadow-blue-900/20"
|
|
||||||
>
|
|
||||||
ЗАРЕГИСТРИРОВАТЬ
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user