Álvaro Valenzuela Valdes commited on
Commit ·
ff8bae0
1
Parent(s): 4667270
🚀 Fix: Company profile persistence and input logic
Browse files- backend/app/routers/company.py +22 -22
- frontend/components/CompanyProfile.tsx +18 -17
backend/app/routers/company.py
CHANGED
|
@@ -9,10 +9,12 @@ router = APIRouter()
|
|
| 9 |
|
| 10 |
@router.post("/company-profile", response_model=CompanyProfile)
|
| 11 |
def save_company_profile(profile: CompanyProfile, db: Session = Depends(get_db)):
|
|
|
|
| 12 |
# Try to find existing profile (assume only one for now)
|
| 13 |
db_profile = db.query(CompanyProfileModel).first()
|
| 14 |
|
| 15 |
if not db_profile:
|
|
|
|
| 16 |
db_profile = CompanyProfileModel()
|
| 17 |
db.add(db_profile)
|
| 18 |
|
|
@@ -25,39 +27,37 @@ def save_company_profile(profile: CompanyProfile, db: Session = Depends(get_db))
|
|
| 25 |
db_profile.documents_available = json.dumps(profile.documents_available)
|
| 26 |
|
| 27 |
db.commit()
|
| 28 |
-
|
| 29 |
return profile
|
| 30 |
|
| 31 |
@router.get("/company-profile", response_model=CompanyProfile)
|
| 32 |
def get_company_profile(db: Session = Depends(get_db)):
|
| 33 |
db_profile = db.query(CompanyProfileModel).first()
|
| 34 |
if not db_profile:
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
# Handle list fields that are stored as JSON strings
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
try: services = json.loads(db_profile.services) if db_profile.services else []
|
| 44 |
-
except: services = [db_profile.services] if db_profile.services else []
|
| 45 |
-
|
| 46 |
-
try: certifications = json.loads(db_profile.certifications) if db_profile.certifications else []
|
| 47 |
-
except: certifications = []
|
| 48 |
-
|
| 49 |
-
try: regions = json.loads(db_profile.regions) if db_profile.regions else []
|
| 50 |
-
except: regions = [db_profile.regions] if db_profile.regions else []
|
| 51 |
-
|
| 52 |
-
try: docs = json.loads(db_profile.documents_available) if db_profile.documents_available else []
|
| 53 |
-
except: docs = [db_profile.documents_available] if db_profile.documents_available else []
|
| 54 |
|
| 55 |
return CompanyProfile(
|
| 56 |
name=db_profile.name,
|
| 57 |
industry=db_profile.industry,
|
| 58 |
-
services=services,
|
| 59 |
experience=db_profile.experience,
|
| 60 |
-
certifications=certifications,
|
| 61 |
-
regions=regions,
|
| 62 |
-
documents_available=
|
| 63 |
)
|
|
|
|
| 9 |
|
| 10 |
@router.post("/company-profile", response_model=CompanyProfile)
|
| 11 |
def save_company_profile(profile: CompanyProfile, db: Session = Depends(get_db)):
|
| 12 |
+
print(f"!!! SAVING PROFILE: {profile.name} !!!")
|
| 13 |
# Try to find existing profile (assume only one for now)
|
| 14 |
db_profile = db.query(CompanyProfileModel).first()
|
| 15 |
|
| 16 |
if not db_profile:
|
| 17 |
+
print("Creating NEW profile in DB")
|
| 18 |
db_profile = CompanyProfileModel()
|
| 19 |
db.add(db_profile)
|
| 20 |
|
|
|
|
| 27 |
db_profile.documents_available = json.dumps(profile.documents_available)
|
| 28 |
|
| 29 |
db.commit()
|
| 30 |
+
print("!!! PROFILE SAVED SUCCESSFULLY !!!")
|
| 31 |
return profile
|
| 32 |
|
| 33 |
@router.get("/company-profile", response_model=CompanyProfile)
|
| 34 |
def get_company_profile(db: Session = Depends(get_db)):
|
| 35 |
db_profile = db.query(CompanyProfileModel).first()
|
| 36 |
if not db_profile:
|
| 37 |
+
print("No profile found, returning default")
|
| 38 |
+
return CompanyProfile(
|
| 39 |
+
name="Andes Digital",
|
| 40 |
+
industry="Tecnología",
|
| 41 |
+
services=["Automatización AI", "Desarrollo Software"],
|
| 42 |
+
experience="5 años en el sector",
|
| 43 |
+
certifications=[],
|
| 44 |
+
regions=["Metropolitana"],
|
| 45 |
+
documents_available=["RUT"]
|
| 46 |
+
)
|
| 47 |
|
| 48 |
# Handle list fields that are stored as JSON strings
|
| 49 |
+
def safe_json_load(field, default=[]):
|
| 50 |
+
try:
|
| 51 |
+
return json.loads(field) if field else default
|
| 52 |
+
except:
|
| 53 |
+
return [field] if field else default
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
return CompanyProfile(
|
| 56 |
name=db_profile.name,
|
| 57 |
industry=db_profile.industry,
|
| 58 |
+
services=safe_json_load(db_profile.services, ["General"]),
|
| 59 |
experience=db_profile.experience,
|
| 60 |
+
certifications=safe_json_load(db_profile.certifications),
|
| 61 |
+
regions=safe_json_load(db_profile.regions, ["Nacional"]),
|
| 62 |
+
documents_available=safe_json_load(db_profile.documents_available)
|
| 63 |
)
|
frontend/components/CompanyProfile.tsx
CHANGED
|
@@ -10,19 +10,20 @@ type Props = {
|
|
| 10 |
|
| 11 |
export default function CompanyProfile({ profile, onSave }: Props) {
|
| 12 |
const [form, setForm] = useState(profile);
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
const
|
| 16 |
-
const
|
| 17 |
-
const
|
|
|
|
| 18 |
|
| 19 |
const handleSave = () => {
|
| 20 |
onSave({
|
| 21 |
...form,
|
| 22 |
-
services:
|
| 23 |
-
certifications:
|
| 24 |
-
regions:
|
| 25 |
-
documents_available:
|
| 26 |
});
|
| 27 |
};
|
| 28 |
|
|
@@ -51,8 +52,8 @@ export default function CompanyProfile({ profile, onSave }: Props) {
|
|
| 51 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 52 |
<span className="text-sm text-slate-400">Services</span>
|
| 53 |
<input
|
| 54 |
-
value={
|
| 55 |
-
onChange={(event) =>
|
| 56 |
placeholder="AI automation, web apps, data dashboards"
|
| 57 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 58 |
/>
|
|
@@ -71,8 +72,8 @@ export default function CompanyProfile({ profile, onSave }: Props) {
|
|
| 71 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 72 |
<span className="text-sm text-slate-400">Certifications</span>
|
| 73 |
<input
|
| 74 |
-
value={
|
| 75 |
-
onChange={(event) =>
|
| 76 |
placeholder="ISO 9001, ISO 27001"
|
| 77 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 78 |
/>
|
|
@@ -80,8 +81,8 @@ export default function CompanyProfile({ profile, onSave }: Props) {
|
|
| 80 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 81 |
<span className="text-sm text-slate-400">Regions</span>
|
| 82 |
<input
|
| 83 |
-
value={
|
| 84 |
-
onChange={(event) =>
|
| 85 |
placeholder="Metropolitana, Valparaíso"
|
| 86 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 87 |
/>
|
|
@@ -91,8 +92,8 @@ export default function CompanyProfile({ profile, onSave }: Props) {
|
|
| 91 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 92 |
<span className="text-sm text-slate-400">Documents available</span>
|
| 93 |
<input
|
| 94 |
-
value={
|
| 95 |
-
onChange={(event) =>
|
| 96 |
placeholder="RUT, Portfolio, Financial statements"
|
| 97 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 98 |
/>
|
|
|
|
| 10 |
|
| 11 |
export default function CompanyProfile({ profile, onSave }: Props) {
|
| 12 |
const [form, setForm] = useState(profile);
|
| 13 |
+
|
| 14 |
+
// Use local strings for editing lists
|
| 15 |
+
const [servicesStr, setServicesStr] = useState(profile.services.join(", "));
|
| 16 |
+
const [certsStr, setCertsStr] = useState(profile.certifications?.join(", ") || "");
|
| 17 |
+
const [regionsStr, setRegionsStr] = useState(profile.regions?.join(", ") || "");
|
| 18 |
+
const [docsStr, setDocsStr] = useState(profile.documents_available?.join(", ") || "");
|
| 19 |
|
| 20 |
const handleSave = () => {
|
| 21 |
onSave({
|
| 22 |
...form,
|
| 23 |
+
services: servicesStr.split(",").map((s) => s.trim()).filter(Boolean),
|
| 24 |
+
certifications: certsStr.split(",").map((s) => s.trim()).filter(Boolean),
|
| 25 |
+
regions: regionsStr.split(",").map((s) => s.trim()).filter(Boolean),
|
| 26 |
+
documents_available: docsStr.split(",").map((s) => s.trim()).filter(Boolean),
|
| 27 |
});
|
| 28 |
};
|
| 29 |
|
|
|
|
| 52 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 53 |
<span className="text-sm text-slate-400">Services</span>
|
| 54 |
<input
|
| 55 |
+
value={servicesStr}
|
| 56 |
+
onChange={(event) => setServicesStr(event.target.value)}
|
| 57 |
placeholder="AI automation, web apps, data dashboards"
|
| 58 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 59 |
/>
|
|
|
|
| 72 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 73 |
<span className="text-sm text-slate-400">Certifications</span>
|
| 74 |
<input
|
| 75 |
+
value={certsStr}
|
| 76 |
+
onChange={(event) => setCertsStr(event.target.value)}
|
| 77 |
placeholder="ISO 9001, ISO 27001"
|
| 78 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 79 |
/>
|
|
|
|
| 81 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 82 |
<span className="text-sm text-slate-400">Regions</span>
|
| 83 |
<input
|
| 84 |
+
value={regionsStr}
|
| 85 |
+
onChange={(event) => setRegionsStr(event.target.value)}
|
| 86 |
placeholder="Metropolitana, Valparaíso"
|
| 87 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 88 |
/>
|
|
|
|
| 92 |
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
|
| 93 |
<span className="text-sm text-slate-400">Documents available</span>
|
| 94 |
<input
|
| 95 |
+
value={docsStr}
|
| 96 |
+
onChange={(event) => setDocsStr(event.target.value)}
|
| 97 |
placeholder="RUT, Portfolio, Financial statements"
|
| 98 |
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
|
| 99 |
/>
|