fix:(equipe) ajustado cadastro por regiao no acesso master
This commit is contained in:
parent
82b597bda3
commit
c5f1c40243
4 changed files with 37 additions and 12 deletions
|
|
@ -282,21 +282,24 @@ func (h *Handler) Create(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Security: Only allow TargetUserID if user is ADMIN or OWNER
|
// Security: Only allow TargetUserID if user is ADMIN or OWNER
|
||||||
|
// Also handle Region override
|
||||||
|
userRole, _ := c.Get("role")
|
||||||
|
roleStr, _ := userRole.(string)
|
||||||
|
|
||||||
if input.TargetUserID != nil && *input.TargetUserID != "" {
|
if input.TargetUserID != nil && *input.TargetUserID != "" {
|
||||||
userRole, exists := c.Get("role")
|
if roleStr != "SUPERADMIN" && roleStr != "BUSINESS_OWNER" {
|
||||||
if !exists {
|
|
||||||
// Should validation fail? Or just ignore target?
|
|
||||||
// Safer to ignore target user ID if role not found
|
|
||||||
input.TargetUserID = nil
|
input.TargetUserID = nil
|
||||||
} else {
|
|
||||||
roleStr, ok := userRole.(string)
|
|
||||||
if !ok || (roleStr != "SUPERADMIN" && roleStr != "BUSINESS_OWNER") {
|
|
||||||
input.TargetUserID = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regiao := c.GetString("regiao")
|
regiao := c.GetString("regiao")
|
||||||
|
// If input has regiao and user is admin, use it
|
||||||
|
if input.Regiao != nil && *input.Regiao != "" {
|
||||||
|
if roleStr == "SUPERADMIN" || roleStr == "BUSINESS_OWNER" {
|
||||||
|
regiao = *input.Regiao
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
prof, err := h.service.Create(c.Request.Context(), userIDStr, input, regiao)
|
prof, err := h.service.Create(c.Request.Context(), userIDStr, input, regiao)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ type CreateProfissionalInput struct {
|
||||||
Email *string `json:"email"`
|
Email *string `json:"email"`
|
||||||
AvatarURL *string `json:"avatar_url"`
|
AvatarURL *string `json:"avatar_url"`
|
||||||
TargetUserID *string `json:"target_user_id"` // Optional: For admin creation
|
TargetUserID *string `json:"target_user_id"` // Optional: For admin creation
|
||||||
|
Regiao *string `json:"regiao"` // Optional: Override region
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Create(ctx context.Context, userID string, input CreateProfissionalInput, regiao string) (*generated.GetProfissionalByIDRow, error) {
|
func (s *Service) Create(ctx context.Context, userID string, input CreateProfissionalInput, regiao string) (*generated.GetProfissionalByIDRow, error) {
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,12 @@ export const ProfessionalModal: React.FC<ProfessionalModalProps> = ({
|
||||||
roles,
|
roles,
|
||||||
onSuccess,
|
onSuccess,
|
||||||
}) => {
|
}) => {
|
||||||
const { token: contextToken } = useAuth();
|
const { token: contextToken, user } = useAuth(); // Get User
|
||||||
const token = contextToken || "";
|
const token = contextToken || "";
|
||||||
|
|
||||||
const initialFormState: CreateProfessionalDTO & { senha?: string; confirmarSenha?: string } = {
|
const initialFormState: CreateProfessionalDTO & { senha?: string; confirmarSenha?: string } = {
|
||||||
nome: "",
|
nome: "",
|
||||||
|
regiao: "",
|
||||||
funcao_profissional_id: "",
|
funcao_profissional_id: "",
|
||||||
funcoes_ids: [],
|
funcoes_ids: [],
|
||||||
email: "",
|
email: "",
|
||||||
|
|
@ -87,6 +88,7 @@ export const ProfessionalModal: React.FC<ProfessionalModalProps> = ({
|
||||||
// Edit Mode
|
// Edit Mode
|
||||||
setFormData({
|
setFormData({
|
||||||
nome: professional.nome,
|
nome: professional.nome,
|
||||||
|
regiao: professional.regiao || "",
|
||||||
funcao_profissional_id: professional.funcao_profissional_id,
|
funcao_profissional_id: professional.funcao_profissional_id,
|
||||||
funcoes_ids: professional.functions?.map(f => f.id) || (professional.funcao_profissional_id ? [professional.funcao_profissional_id] : []),
|
funcoes_ids: professional.functions?.map(f => f.id) || (professional.funcao_profissional_id ? [professional.funcao_profissional_id] : []),
|
||||||
email: professional.email || "",
|
email: professional.email || "",
|
||||||
|
|
@ -119,12 +121,13 @@ export const ProfessionalModal: React.FC<ProfessionalModalProps> = ({
|
||||||
setAvatarPreview(professional.avatar_url || (professional.avatar ?? GenericAvatar));
|
setAvatarPreview(professional.avatar_url || (professional.avatar ?? GenericAvatar));
|
||||||
} else {
|
} else {
|
||||||
// Add Mode
|
// Add Mode
|
||||||
setFormData(initialFormState);
|
const defaultRegion = user?.allowedRegions && user.allowedRegions.length > 0 ? user.allowedRegions[0] : "SP";
|
||||||
|
setFormData({ ...initialFormState, regiao: defaultRegion });
|
||||||
setAvatarPreview("");
|
setAvatarPreview("");
|
||||||
}
|
}
|
||||||
setAvatarFile(null);
|
setAvatarFile(null);
|
||||||
}
|
}
|
||||||
}, [isOpen, professional]);
|
}, [isOpen, professional]); // user dependency intentionally omitted to avoid reset loop, but safe to add if needed
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
const maskPhone = (value: string) => {
|
const maskPhone = (value: string) => {
|
||||||
|
|
@ -387,6 +390,22 @@ export const ProfessionalModal: React.FC<ProfessionalModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Region Selection (Only for Multi-Region Admins) */}
|
||||||
|
{(user?.allowedRegions && user.allowedRegions.length > 1) || user?.role === "SUPERADMIN" ? (
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">Região de Atuação *</label>
|
||||||
|
<select
|
||||||
|
value={formData.regiao || ""}
|
||||||
|
onChange={e => setFormData({ ...formData, regiao: e.target.value })}
|
||||||
|
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-brand-gold focus:ring focus:ring-brand-gold focus:ring-opacity-50 p-2 border"
|
||||||
|
>
|
||||||
|
<option value="SP">São Paulo (SP)</option>
|
||||||
|
<option value="MG">Minas Gerais (MG)</option>
|
||||||
|
</select>
|
||||||
|
<p className="text-xs text-gray-500 mt-1">Selecione onde este profissional irá atuar.</p>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{/* Seleção de Função (Movida para o topo) */}
|
{/* Seleção de Função (Movida para o topo) */}
|
||||||
<div className="col-span-1 md:col-span-2 mb-4">
|
<div className="col-span-1 md:col-span-2 mb-4">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ export interface Professional {
|
||||||
id: string;
|
id: string;
|
||||||
usuario_id?: string;
|
usuario_id?: string;
|
||||||
nome: string;
|
nome: string;
|
||||||
|
regiao?: string; // Add region to interface
|
||||||
name?: string; // Restore for compatibility
|
name?: string; // Restore for compatibility
|
||||||
email?: string;
|
email?: string;
|
||||||
funcao_profissional_id: string;
|
funcao_profissional_id: string;
|
||||||
|
|
@ -209,6 +210,7 @@ export interface Professional {
|
||||||
|
|
||||||
export interface CreateProfessionalDTO {
|
export interface CreateProfessionalDTO {
|
||||||
nome: string;
|
nome: string;
|
||||||
|
regiao?: string;
|
||||||
funcao_profissional_id: string; // Keep for compatibility (primary function)
|
funcao_profissional_id: string; // Keep for compatibility (primary function)
|
||||||
funcoes_ids?: string[]; // New multi-select
|
funcoes_ids?: string[]; // New multi-select
|
||||||
email?: string;
|
email?: string;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue