fix: fix several different data parsing issues
This commit is contained in:
@@ -27,6 +27,21 @@
|
||||
country?: string;
|
||||
}
|
||||
|
||||
interface CompanySite {
|
||||
id?: number;
|
||||
uid?: string;
|
||||
name?: string;
|
||||
defaultFlag?: boolean;
|
||||
inactiveFlag?: boolean;
|
||||
addressLine1?: string | null;
|
||||
addressLine2?: string | null;
|
||||
city?: string | null;
|
||||
state?: string | null;
|
||||
zip?: string | null;
|
||||
country?: string | null;
|
||||
phone?: string | null;
|
||||
}
|
||||
|
||||
export let isOpen = false;
|
||||
export let onSuccess: () => void = () => {};
|
||||
export let opportunityTypes: OpportunityType[] = [];
|
||||
@@ -48,6 +63,8 @@
|
||||
let contacts: CompanyContact[] = [];
|
||||
let selectedContactId = "";
|
||||
let companyAddress: CompanyAddress | null = null;
|
||||
let allAddresses: CompanySite[] = [];
|
||||
let selectedSiteUid: string | null = null;
|
||||
let isLoadingCompanyDetails = false;
|
||||
|
||||
// ── UI state ──
|
||||
@@ -112,6 +129,11 @@
|
||||
(c) => String(c.cwId) === selectedContactId,
|
||||
);
|
||||
$: activeContacts = contacts.filter((c) => !c.inactive);
|
||||
$: activeSites = allAddresses.filter((a) => !a.inactiveFlag);
|
||||
$: selectedSite =
|
||||
selectedSiteUid !== null
|
||||
? (activeSites.find((a) => a.uid === selectedSiteUid) ?? null)
|
||||
: (activeSites.find((a) => a.defaultFlag) ?? activeSites[0] ?? null);
|
||||
|
||||
// ── Default close date to 30 days from now ──
|
||||
$: if (isOpen && !expectedCloseDate) {
|
||||
@@ -211,6 +233,8 @@
|
||||
contacts = [];
|
||||
selectedContactId = "";
|
||||
companyAddress = null;
|
||||
allAddresses = [];
|
||||
selectedSiteUid = null;
|
||||
}
|
||||
|
||||
function handleCompanyKeydown(e: KeyboardEvent) {
|
||||
@@ -247,6 +271,8 @@
|
||||
contacts = [];
|
||||
selectedContactId = "";
|
||||
companyAddress = null;
|
||||
allAddresses = [];
|
||||
selectedSiteUid = null;
|
||||
}
|
||||
|
||||
// ── Load company details (contacts + address) ──
|
||||
@@ -259,6 +285,7 @@
|
||||
cw_Data?: {
|
||||
allContacts?: CompanyContact[];
|
||||
address?: CompanyAddress;
|
||||
allAddresses?: CompanySite[];
|
||||
};
|
||||
};
|
||||
}>(`/api/companies/${companyOptimaId}/details`);
|
||||
@@ -268,6 +295,12 @@
|
||||
const allContacts: CompanyContact[] = data.cw_Data?.allContacts ?? [];
|
||||
contacts = allContacts;
|
||||
companyAddress = data.cw_Data?.address ?? null;
|
||||
allAddresses = data.cw_Data?.allAddresses ?? [];
|
||||
|
||||
// Auto-select default/first active site
|
||||
const activeAddr = allAddresses.filter((a) => !a.inactiveFlag);
|
||||
const defaultAddr = activeAddr.find((a) => a.defaultFlag) ?? activeAddr[0];
|
||||
selectedSiteUid = defaultAddr?.uid ?? null;
|
||||
|
||||
// Auto-select first active contact as default
|
||||
const active = allContacts.filter((c: CompanyContact) => !c.inactive);
|
||||
@@ -393,6 +426,8 @@
|
||||
contacts = [];
|
||||
selectedContactId = "";
|
||||
companyAddress = null;
|
||||
allAddresses = [];
|
||||
selectedSiteUid = null;
|
||||
isLoadingCompanyDetails = false;
|
||||
isSubmitting = false;
|
||||
submitError = "";
|
||||
@@ -1116,39 +1151,63 @@
|
||||
</svg>
|
||||
Loading site information…
|
||||
</div>
|
||||
{:else if companyAddress}
|
||||
<div class="co-site-card">
|
||||
<div class="co-site-card-icon">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
width="20"
|
||||
height="20"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
{:else if activeSites.length > 0}
|
||||
{#if activeSites.length > 1}
|
||||
<div class="co-form-grid">
|
||||
<div class="co-form-group co-full-width">
|
||||
<label for="co-site-select">Site</label>
|
||||
<select
|
||||
id="co-site-select"
|
||||
bind:value={selectedSiteUid}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{#each activeSites as site}
|
||||
<option value={site.uid}>
|
||||
{site.name || site.addressLine1 || "Unnamed Site"}{site.defaultFlag ? " (Default)" : ""}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="co-site-card-details">
|
||||
<p class="co-site-label">Primary Address</p>
|
||||
<p class="co-site-line">{companyAddress.line1 ?? ""}</p>
|
||||
{#if companyAddress.line2}
|
||||
<p class="co-site-line">{companyAddress.line2}</p>
|
||||
{/if}
|
||||
<p class="co-site-line">
|
||||
{companyAddress.city ?? ""}{companyAddress.city &&
|
||||
companyAddress.state
|
||||
? ", "
|
||||
: ""}{companyAddress.state ?? ""}
|
||||
{companyAddress.zip ?? ""}
|
||||
</p>
|
||||
{#if companyAddress.country && companyAddress.country !== "United States"}
|
||||
<p class="co-site-line">{companyAddress.country}</p>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if selectedSite}
|
||||
<div class="co-site-card">
|
||||
<div class="co-site-card-icon">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
width="20"
|
||||
height="20"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="co-site-card-details">
|
||||
{#if selectedSite.name}
|
||||
<p class="co-site-label">{selectedSite.name}</p>
|
||||
{/if}
|
||||
{#if selectedSite.addressLine1}
|
||||
<p class="co-site-line">{selectedSite.addressLine1}</p>
|
||||
{/if}
|
||||
{#if selectedSite.addressLine2}
|
||||
<p class="co-site-line">{selectedSite.addressLine2}</p>
|
||||
{/if}
|
||||
<p class="co-site-line">
|
||||
{selectedSite.city ?? ""}{selectedSite.city && selectedSite.state ? ", " : ""}{selectedSite.state ?? ""}
|
||||
{selectedSite.zip ?? ""}
|
||||
</p>
|
||||
{#if selectedSite.country && selectedSite.country !== "United States"}
|
||||
<p class="co-site-line">{selectedSite.country}</p>
|
||||
{/if}
|
||||
{#if selectedSite.phone}
|
||||
<p class="co-site-line">{selectedSite.phone}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="co-empty-state">
|
||||
<svg
|
||||
@@ -1293,14 +1352,13 @@
|
||||
: "—"}
|
||||
</dd>
|
||||
</div>
|
||||
{#if companyAddress}
|
||||
{#if selectedSite}
|
||||
<div class="co-review-item">
|
||||
<dt>Site</dt>
|
||||
<dd>
|
||||
{companyAddress.city ?? ""}{companyAddress.city &&
|
||||
companyAddress.state
|
||||
? ", "
|
||||
: ""}{companyAddress.state ?? ""}
|
||||
{selectedSite.name
|
||||
? selectedSite.name
|
||||
: `${selectedSite.city ?? ""}${selectedSite.city && selectedSite.state ? ", " : ""}${selectedSite.state ?? ""}`}
|
||||
</dd>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -8,12 +8,16 @@ export const company = {
|
||||
includeAddress?: boolean;
|
||||
includePrimaryContact?: boolean;
|
||||
includeAllContacts?: boolean;
|
||||
includeAllAddresses?: boolean;
|
||||
},
|
||||
) {
|
||||
|
||||
const params: Record<string, string> = {};
|
||||
if (options?.includeAddress) params.includeAddress = "true";
|
||||
if (options?.includePrimaryContact) params.includePrimaryContact = "true";
|
||||
if (options?.includeAllContacts) params.includeAllContacts = "true";
|
||||
if (options?.includeAllAddresses) params.includeAllAddresses = "true";
|
||||
|
||||
|
||||
const company = await api.get(`/v1/company/companies/${id}`, {
|
||||
params,
|
||||
@@ -21,6 +25,8 @@ export const company = {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(company.data);
|
||||
return company.data;
|
||||
},
|
||||
async fetchMany(
|
||||
|
||||
@@ -9,10 +9,13 @@ export const GET: RequestHandler = async ({ params, locals }) => {
|
||||
return json({ data: null }, { status: 401 });
|
||||
}
|
||||
|
||||
console.log("Here")
|
||||
|
||||
try {
|
||||
const result = await optima.company.fetch(accessToken, params.id, {
|
||||
includeAllContacts: true,
|
||||
includeAddress: true,
|
||||
includeAllAddresses: true,
|
||||
});
|
||||
return json({ data: result?.data ?? null });
|
||||
} catch (err) {
|
||||
|
||||
@@ -51,6 +51,7 @@ export const load: PageServerLoad = async ({ locals, params }) => {
|
||||
includeAddress: permissions["company.fetch.address"] === true,
|
||||
includePrimaryContact: true,
|
||||
includeAllContacts: permissions["company.fetch.contacts"] === true,
|
||||
includeAllAddresses: permissions["company.fetch.address"] === true,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -15,6 +15,27 @@
|
||||
export let permissions: PermissionMap;
|
||||
export let isMobile: boolean;
|
||||
export let mobileActiveTab: string | null;
|
||||
|
||||
// Selected site for the sites dropdown
|
||||
let selectedSiteUid: string | null = null;
|
||||
$: allAddresses = company?.cw_Data?.allAddresses ?? [];
|
||||
$: activeSites = allAddresses.filter((a) => !a.inactiveFlag);
|
||||
$: selectedSite =
|
||||
selectedSiteUid !== null
|
||||
? activeSites.find((a) => a.uid === selectedSiteUid) ?? null
|
||||
: activeSites.find((a) => a.defaultFlag) ?? activeSites[0] ?? null;
|
||||
|
||||
function formatSiteAddress(site: (typeof activeSites)[number]): string[] {
|
||||
const lines: string[] = [];
|
||||
if (site.addressLine1) lines.push(site.addressLine1);
|
||||
if (site.addressLine2) lines.push(site.addressLine2);
|
||||
const cityStateZip = [site.city, site.state, site.zip]
|
||||
.filter(Boolean)
|
||||
.join(", ");
|
||||
if (cityStateZip) lines.push(cityStateZip);
|
||||
if (site.country) lines.push(site.country);
|
||||
return lines;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -170,7 +191,54 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if permissions["company.fetch.address"] && formatAddress(company).length > 0}
|
||||
{#if permissions["company.fetch.address"] && activeSites.length > 0}
|
||||
<div class="info-row">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
class="info-icon"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
<div class="info-content">
|
||||
{#if activeSites.length > 1}
|
||||
<select
|
||||
class="site-select"
|
||||
bind:value={selectedSiteUid}
|
||||
on:change={(e) => (selectedSiteUid = e.currentTarget.value)}
|
||||
>
|
||||
{#each activeSites as site}
|
||||
<option value={site.uid}>
|
||||
{site.name}{site.defaultFlag ? " (Default)" : ""}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<span class="info-label"
|
||||
>{activeSites[0]?.name ?? "Address"}</span
|
||||
>
|
||||
{/if}
|
||||
{#if selectedSite}
|
||||
{@const lines = formatSiteAddress(selectedSite)}
|
||||
{#if lines.length > 0}
|
||||
<span class="info-value address-multiline">
|
||||
{#each lines as line}
|
||||
{line}<br />
|
||||
{/each}
|
||||
</span>
|
||||
{/if}
|
||||
{#if selectedSite.phone}
|
||||
<span class="info-value site-phone"
|
||||
>{formatPhone(selectedSite.phone)}</span
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{:else if permissions["company.fetch.address"] && formatAddress(company).length > 0}
|
||||
<div class="info-row">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -27,6 +27,21 @@ export interface CompanyData {
|
||||
zip?: string;
|
||||
country?: string;
|
||||
};
|
||||
allAddresses?: Array<{
|
||||
id: number;
|
||||
uid: string;
|
||||
name: string;
|
||||
description?: string | null;
|
||||
defaultFlag: boolean;
|
||||
inactiveFlag: boolean;
|
||||
addressLine1?: string | null;
|
||||
addressLine2?: string | null;
|
||||
city?: string | null;
|
||||
state?: string | null;
|
||||
zip?: string | null;
|
||||
country?: string | null;
|
||||
phone?: string | null;
|
||||
}>;
|
||||
primaryContact?: {
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
|
||||
@@ -411,6 +411,29 @@
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.site-select {
|
||||
width: 100%;
|
||||
padding: 4px 6px;
|
||||
border: 1px solid var(--border-color, #e5e7eb);
|
||||
border-radius: 6px;
|
||||
background: var(--bg-secondary, #f9fafb);
|
||||
color: var(--text-primary, #111827);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.site-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-color, #6366f1);
|
||||
}
|
||||
|
||||
.info-value.site-phone {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* Primary contact section */
|
||||
.primary-contact-section {
|
||||
margin-top: 8px;
|
||||
|
||||
Reference in New Issue
Block a user