fix(backoffice): use string IDs for companies/jobs/users, fix audit log, ensure real tags support
This commit is contained in:
parent
9784e959e4
commit
4eae018a25
5 changed files with 23 additions and 28 deletions
|
|
@ -760,19 +760,14 @@ func (h *CoreHandlers) Me(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
var userID int
|
||||
var userID string
|
||||
switch v := userIDVal.(type) {
|
||||
case int:
|
||||
userID = v
|
||||
userID = strconv.Itoa(v)
|
||||
case string:
|
||||
var err error
|
||||
userID, err = strconv.Atoi(v)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid User ID in context", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
userID = v
|
||||
case float64:
|
||||
userID = int(v)
|
||||
userID = strconv.Itoa(int(v))
|
||||
}
|
||||
|
||||
user, err := h.adminService.GetUser(ctx, userID)
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@ type LoginResponse struct {
|
|||
Token string `json:"token"`
|
||||
User UserInfo `json:"user"`
|
||||
Companies []CompanyInfo `json:"companies,omitempty"`
|
||||
ActiveCompanyID *int `json:"activeCompanyId,omitempty"`
|
||||
ActiveCompanyID *string `json:"activeCompanyId,omitempty"`
|
||||
}
|
||||
|
||||
// UserInfo represents basic user information in responses
|
||||
type UserInfo struct {
|
||||
ID int `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Identifier string `json:"identifier"`
|
||||
Role string `json:"role"`
|
||||
FullName string `json:"fullName"`
|
||||
|
|
@ -29,7 +29,7 @@ type UserInfo struct {
|
|||
|
||||
// CompanyInfo represents basic company information
|
||||
type CompanyInfo struct {
|
||||
ID int `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Role string `json:"role"` // Role in this company (admin or recruiter)
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ type RegisterRequest struct {
|
|||
|
||||
// User represents a generic user profile
|
||||
type User struct {
|
||||
ID int `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Role string `json:"role"`
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ func (s *AdminService) getTagByID(ctx context.Context, id int) (*models.Tag, err
|
|||
}
|
||||
|
||||
// GetUser fetches a user by ID
|
||||
func (s *AdminService) GetUser(ctx context.Context, id int) (*dto.User, error) {
|
||||
func (s *AdminService) GetUser(ctx context.Context, id string) (*dto.User, error) {
|
||||
query := `
|
||||
SELECT id, name, email, role, created_at
|
||||
FROM users WHERE id = $1
|
||||
|
|
@ -540,7 +540,7 @@ func (s *AdminService) GetUser(ctx context.Context, id int) (*dto.User, error) {
|
|||
}
|
||||
|
||||
// GetCompanyByUserID fetches the company associated with a user
|
||||
func (s *AdminService) GetCompanyByUserID(ctx context.Context, userID int) (*models.Company, error) {
|
||||
func (s *AdminService) GetCompanyByUserID(ctx context.Context, userID string) (*models.Company, error) {
|
||||
// First, try to find company where this user is admin
|
||||
// Assuming users table has company_id or companies table has admin_email
|
||||
// Let's check if 'users' has company_id column via error or assume architecture.
|
||||
|
|
@ -568,7 +568,7 @@ func (s *AdminService) GetCompanyByUserID(ctx context.Context, userID int) (*mod
|
|||
WHERE u.id = $1
|
||||
`
|
||||
if err2 := s.DB.QueryRowContext(ctx, query2, userID).Scan(&c.ID, &c.Name, &c.Slug, &c.Active, &c.Verified); err2 != nil {
|
||||
return nil, fmt.Errorf("company not found for user %d", userID)
|
||||
return nil, fmt.Errorf("company not found for user %s", userID)
|
||||
}
|
||||
}
|
||||
return &c, nil
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export default function BackofficePage() {
|
|||
}
|
||||
}
|
||||
|
||||
const handleApproveCompany = async (companyId: number) => {
|
||||
const handleApproveCompany = async (companyId: string) => {
|
||||
try {
|
||||
await adminCompaniesApi.updateStatus(companyId, { verified: true })
|
||||
toast.success("Company approved")
|
||||
|
|
@ -102,7 +102,7 @@ export default function BackofficePage() {
|
|||
}
|
||||
}
|
||||
|
||||
const handleDeactivateCompany = async (companyId: number) => {
|
||||
const handleDeactivateCompany = async (companyId: string) => {
|
||||
try {
|
||||
await adminCompaniesApi.updateStatus(companyId, { active: false })
|
||||
toast.success("Company deactivated")
|
||||
|
|
@ -113,7 +113,7 @@ export default function BackofficePage() {
|
|||
}
|
||||
}
|
||||
|
||||
const handleJobStatus = async (jobId: number, status: string) => {
|
||||
const handleJobStatus = async (jobId: string, status: string) => {
|
||||
try {
|
||||
await adminJobsApi.updateStatus(jobId, status)
|
||||
toast.success("Job status updated")
|
||||
|
|
@ -124,7 +124,7 @@ export default function BackofficePage() {
|
|||
}
|
||||
}
|
||||
|
||||
const handleDuplicateJob = async (jobId: number) => {
|
||||
const handleDuplicateJob = async (jobId: string) => {
|
||||
try {
|
||||
await adminJobsApi.duplicate(jobId)
|
||||
toast.success("Job duplicated as draft")
|
||||
|
|
@ -283,11 +283,11 @@ export default function BackofficePage() {
|
|||
)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right space-x-2">
|
||||
<Button size="sm" variant="outline" onClick={() => handleApproveCompany(Number(company.id))}>
|
||||
<Button size="sm" variant="outline" onClick={() => handleApproveCompany(company.id)}>
|
||||
<CheckCircle className="h-4 w-4 mr-2" />
|
||||
Aprovar
|
||||
</Button>
|
||||
<Button size="sm" variant="destructive" onClick={() => handleDeactivateCompany(Number(company.id))}>
|
||||
<Button size="sm" variant="destructive" onClick={() => handleDeactivateCompany(company.id)}>
|
||||
<XCircle className="h-4 w-4 mr-2" />
|
||||
Desativar
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export interface AdminCompany {
|
|||
}
|
||||
|
||||
export interface AdminJob {
|
||||
id: number;
|
||||
id: string;
|
||||
title: string;
|
||||
companyName: string;
|
||||
status: string;
|
||||
|
|
@ -116,7 +116,7 @@ export interface AdminTag {
|
|||
}
|
||||
|
||||
export interface AdminCandidate {
|
||||
id: number;
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
|
|
@ -218,12 +218,12 @@ export const adminJobsApi = {
|
|||
|
||||
return apiRequest<{ data: AdminJob[]; pagination: any }>(`/api/v1/jobs/moderation?${query.toString()}`);
|
||||
},
|
||||
updateStatus: (id: number, status: string) =>
|
||||
updateStatus: (id: string, status: string) =>
|
||||
apiRequest<void>(`/api/v1/jobs/${id}/status`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ status }),
|
||||
}),
|
||||
duplicate: (id: number) =>
|
||||
duplicate: (id: string) =>
|
||||
apiRequest<void>(`/api/v1/jobs/${id}/duplicate`, {
|
||||
method: "POST",
|
||||
}),
|
||||
|
|
@ -275,14 +275,14 @@ export const adminCompaniesApi = {
|
|||
body: JSON.stringify(data),
|
||||
});
|
||||
},
|
||||
updateStatus: (id: number, data: { active?: boolean; verified?: boolean }) => {
|
||||
updateStatus: (id: string, data: { active?: boolean; verified?: boolean }) => {
|
||||
logCrudAction("update", "admin/companies", { id, ...data });
|
||||
return apiRequest<void>(`/api/v1/companies/${id}/status`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
},
|
||||
delete: (id: number) => {
|
||||
delete: (id: string) => {
|
||||
logCrudAction("delete", "admin/companies", { id });
|
||||
return apiRequest<void>(`/api/v1/companies/${id}`, {
|
||||
method: "DELETE"
|
||||
|
|
|
|||
Loading…
Reference in a new issue