2025-10-25 11:39:24 +02:00

280 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useState } from "react";
import { useRouter } from "next/navigation";
import "./AddUser.scss";
import { addUser } from "@/services/roles.services";
import { IEditUserForm } from "../User.interfaces";
import { COUNTRY_CODES } from "../constants";
import { formatPhoneDisplay, validatePhone } from "../utils";
interface AddUserFormProps {
onSuccess?: () => void;
}
const AddUserForm: React.FC<AddUserFormProps> = ({ onSuccess }) => {
const router = useRouter();
const [form, setForm] = useState<IEditUserForm>({
username: "",
firstName: "",
lastName: "",
email: "",
phone: "",
role: "",
merchants: [],
groups: [],
jobTitle: "",
});
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [phoneError, setPhoneError] = useState("");
const [countryCode, setCountryCode] = useState("+1");
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
) => {
const { name, value } = e.target;
if (name === "countryCode") {
setCountryCode(value);
return;
}
// Handle array fields (merchants and groups)
if (name === "merchants" || name === "groups") {
if (value === "") {
// If empty selection, set empty array
setForm(prev => ({ ...prev, [name]: [] }));
} else {
// Add the selected value to the array if not already present
setForm(prev => {
const currentArray = prev[name as keyof IEditUserForm] as string[];
if (!currentArray.includes(value)) {
return { ...prev, [name]: [...currentArray, value] };
}
return prev;
});
}
} else {
// Handle single value fields
setForm(prev => ({ ...prev, [name]: value }));
}
};
const handleCountryCodeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const newCountryCode = e.target.value;
setCountryCode(newCountryCode);
// Re-validate phone if it exists
if (form.phone) {
const phoneError = validatePhone(form.phone, newCountryCode);
setPhoneError(phoneError);
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Validate phone number if provided
if (form.phone && phoneError) {
setError("Please fix phone number errors before submitting.");
return;
}
if (
!form.firstName ||
!form.lastName ||
!form.email ||
form.merchants.length === 0 ||
form.groups.length === 0 ||
!form.jobTitle
) {
setError("Please fill in all required fields.");
return;
}
try {
setLoading(true);
setError("");
// Format phone number with country code before submission
const formattedForm = {
...form,
phone: form.phone ? formatPhoneDisplay(form.phone, countryCode) : "",
};
await addUser(formattedForm);
if (onSuccess) onSuccess();
router.refresh(); // <- refreshes the page (SSR re-runs)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
setError(err.message || "Something went wrong.");
} finally {
setLoading(false);
}
};
return (
<form className="add-user" onSubmit={handleSubmit}>
<input
name="username"
placeholder="Username"
value={form.username}
onChange={handleChange}
required
/>
<input
name="firstName"
placeholder="First Name"
value={form.firstName}
onChange={handleChange}
required
/>
<input
name="lastName"
placeholder="Last Name"
value={form.lastName}
onChange={handleChange}
required
/>
<input
name="email"
type="email"
placeholder="Email"
value={form.email}
onChange={handleChange}
required
/>
<div className="array-field-container">
<label>Merchants:</label>
<select
name="merchants"
value=""
onChange={handleChange}
className="add-user__select"
>
<option value="">Select Merchant</option>
<option value="Win Bot">Win Bot</option>
<option value="Data Spin">Data Spin</option>
</select>
{form.merchants.length > 0 && (
<div className="selected-items">
{form.merchants.map((merchant, index) => (
<span key={index} className="selected-item">
{merchant}
<button
type="button"
onClick={() => {
setForm(prev => ({
...prev,
merchants: prev.merchants.filter((_, i) => i !== index),
}));
}}
className="remove-item"
>
×
</button>
</span>
))}
</div>
)}
</div>
<div className="array-field-container">
<label>Groups:</label>
<select
name="groups"
value=""
onChange={handleChange}
className="add-user__select"
>
<option value="">Select Group</option>
<option value="Admin">Admin</option>
<option value="Reader">Reader</option>
<option value="Manager">Manager</option>
<option value="User">User</option>
</select>
{form.groups.length > 0 && (
<div className="selected-items">
{form.groups.map((group, index) => (
<span key={index} className="selected-item">
{group}
<button
type="button"
onClick={() => {
setForm(prev => ({
...prev,
groups: prev.groups.filter((_, i) => i !== index),
}));
}}
className="remove-item"
>
×
</button>
</span>
))}
</div>
)}
</div>
<select
name="jobTitle"
value={form.jobTitle}
onChange={handleChange}
required
className="add-user__select"
>
<option value="">Select Job Title</option>
<option value="Admin">Admin</option>
<option value="Reader">Reader</option>
<option value="User">User</option>
<option value="Manager">Manager</option>
<option value="Supervisor">Supervisor</option>
<option value="Director">Director</option>
</select>
<div className="phone-input-container">
<select
name="countryCode"
value={countryCode}
onChange={handleCountryCodeChange}
className="country-code-select"
>
{COUNTRY_CODES.map(country => (
<option key={country.code} value={country.code}>
{country.flag} {country.code} {country.country}
</option>
))}
</select>
<input
name="phone"
type="tel"
placeholder="Phone number (optional)"
value={form.phone}
onChange={handleChange}
className={phoneError ? "phone-input-error" : ""}
/>
</div>
{error && <span style={{ color: "red", width: "100%" }}>{error}</span>}
<span
className="phone-error-message"
style={{
visibility: phoneError ? "visible" : "hidden",
color: "red",
width: "100%",
}}
>
{phoneError}
</span>
<div className="add-user__button-container">
<button type="submit" disabled={loading}>
{loading ? "Adding..." : "Add User"}
</button>
</div>
</form>
);
};
export default AddUserForm;