AndesOps-AI / frontend /components /CompanyProfile.tsx
Álvaro Valenzuela Valdes
feat: implement IA recommendation engine based on company keywords
8663682
"use client";
import { useState } from "react";
import type { CompanyProfile as CompanyProfileType } from "../lib/types";
type Props = {
profile: CompanyProfileType;
onSave: (profile: CompanyProfileType) => void;
};
export default function CompanyProfile({ profile, onSave }: Props) {
const [form, setForm] = useState(profile);
// Use local strings for editing lists
const [servicesStr, setServicesStr] = useState(profile.services.join(", "));
const [certsStr, setCertsStr] = useState(profile.certifications?.join(", ") || "");
const [regionsStr, setRegionsStr] = useState(profile.regions?.join(", ") || "");
const [docsStr, setDocsStr] = useState(profile.documents_available?.join(", ") || "");
const [keywordsStr, setKeywordsStr] = useState(profile.keywords?.join(", ") || "");
const [saving, setSaving] = useState(false);
const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "success" | "error">("idle");
const handleSave = async () => {
console.log("[CompanyProfile] Clicked Save Profile");
setSaving(true);
setSaveStatus("saving");
try {
const updatedProfile = {
...form,
services: servicesStr.split(",").map((s) => s.trim()).filter(Boolean),
certifications: certsStr.split(",").map((s) => s.trim()).filter(Boolean),
regions: regionsStr.split(",").map((s) => s.trim()).filter(Boolean),
documents_available: docsStr.split(",").map((s) => s.trim()).filter(Boolean),
keywords: keywordsStr.split(",").map((s) => s.trim()).filter(Boolean),
};
console.log("[CompanyProfile] Sending to onSave:", updatedProfile);
await onSave(updatedProfile);
setSaveStatus("success");
setTimeout(() => setSaveStatus("idle"), 3000);
} catch (e) {
console.error("[CompanyProfile] Save failed", e);
setSaveStatus("error");
setTimeout(() => setSaveStatus("idle"), 3000);
} finally {
setSaving(false);
}
};
return (
<div className="space-y-6">
<div className="grid gap-6 lg:grid-cols-2">
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Company name</span>
<input
value={form.name}
onChange={(event) => setForm({ ...form, name: event.target.value })}
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Industry</span>
<input
value={form.industry}
onChange={(event) => setForm({ ...form, industry: event.target.value })}
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
</div>
<div className="grid gap-6 lg:grid-cols-2">
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Services</span>
<input
value={servicesStr}
onChange={(event) => setServicesStr(event.target.value)}
placeholder="AI automation, web apps, data dashboards"
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Experience</span>
<input
value={form.experience}
onChange={(event) => setForm({ ...form, experience: event.target.value })}
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
</div>
<div className="grid gap-6 lg:grid-cols-2">
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Certifications</span>
<input
value={certsStr}
onChange={(event) => setCertsStr(event.target.value)}
placeholder="ISO 9001, ISO 27001"
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Regions</span>
<input
value={regionsStr}
onChange={(event) => setRegionsStr(event.target.value)}
placeholder="Metropolitana, Valparaíso"
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
</div>
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Documents available</span>
<input
value={docsStr}
onChange={(event) => setDocsStr(event.target.value)}
placeholder="RUT, Portfolio, Financial statements"
className="mt-3 w-full rounded-2xl border border-slate-800 bg-slate-900 px-4 py-3 text-white outline-none"
/>
</label>
<label className="block rounded-3xl border border-slate-800 bg-slate-950/80 p-5">
<span className="text-sm text-slate-400">Keywords (for recommendations)</span>
<input
value={keywordsStr}
onChange={(event) => setKeywordsStr(event.target.value)}
placeholder="software, AI, development, consulting"
className="mt-3 w-full rounded-2xl border border-indigo-500/30 bg-slate-900 px-4 py-3 text-white outline-none focus:border-indigo-500 transition-all shadow-[0_0_15px_rgba(99,102,241,0.05)]"
/>
<p className="text-[10px] text-slate-500 mt-2 font-mono uppercase tracking-widest">Separate with commas. These determine your Dashboard recommendations.</p>
</label>
<div className="flex justify-center pt-8 pb-4">
<button
type="button"
onClick={handleSave}
disabled={saving}
className={`group relative overflow-hidden rounded-2xl px-16 py-5 font-bold text-slate-950 transition-all active:scale-95 shadow-2xl ${
saveStatus === "success" ? "bg-green-500 shadow-green-500/40" :
saveStatus === "error" ? "bg-red-500 shadow-red-500/40" :
"bg-cyan hover:bg-sky shadow-cyan/40"
} ${saving ? "opacity-70 cursor-wait" : "cursor-pointer"}`}
>
<span className="relative z-10 flex items-center gap-3">
{saveStatus === "idle" && "Save Profile"}
{saveStatus === "saving" && (
<>
<span className="animate-spin text-xl"></span>
Saving...
</>
)}
{saveStatus === "success" && (
<>
<span className="text-xl"></span>
Saved!
</>
)}
{saveStatus === "error" && (
<>
<span className="text-xl"></span>
Error!
</>
)}
</span>
{saveStatus === "idle" && (
<div className="absolute inset-0 bg-gradient-to-r from-white/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
)}
</button>
</div>
</div>
);
}