Many improvements

This commit is contained in:
2026-06-26 15:48:12 -05:00
parent 2a52e0546e
commit c5725a0259
22 changed files with 1392 additions and 97 deletions
+180 -14
View File
@@ -1,15 +1,8 @@
const treeRadiusRange = {
min: 5,
max: 14,
};
function clamp(value, min, max) {
return Math.min(max, Math.max(min, value));
}
export const featureTypes = {
lotBoundary: {
label: "Lot Boundary",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#7b684d",
weight: 2,
@@ -20,14 +13,35 @@ export const featureTypes = {
},
fence: {
label: "Fence",
geometryType: "LineString",
detailFields: {
fenceType: "string",
},
style: {
color: "#705033",
weight: 4,
opacity: 0.95,
},
},
yardGrid: {
label: "Yard Grid",
geometryType: "LineString",
detailFields: {
axis: "string",
offsetFeet: "number",
spacingFeet: "number",
},
style: (details) => ({
color: details.offsetFeet === 0 ? "#1f4f63" : "#2f7f98",
weight: details.offsetFeet === 0 ? 3 : 2,
opacity: details.offsetFeet === 0 ? 0.75 : 0.55,
dashArray: details.offsetFeet === 0 ? undefined : "6 5",
}),
},
house: {
label: "House",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#8d5a35",
weight: 2,
@@ -37,6 +51,8 @@ export const featureTypes = {
},
garage: {
label: "Garage",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#60636b",
weight: 2,
@@ -46,6 +62,8 @@ export const featureTypes = {
},
porch: {
label: "Porch",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#aa7148",
weight: 2,
@@ -55,6 +73,8 @@ export const featureTypes = {
},
deck: {
label: "Deck",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#7f5a3c",
weight: 2,
@@ -64,6 +84,8 @@ export const featureTypes = {
},
walkway: {
label: "Walkway",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#b8b3a6",
weight: 2,
@@ -73,6 +95,8 @@ export const featureTypes = {
},
driveway: {
label: "Driveway",
geometryType: "Polygon",
detailFields: {},
style: {
color: "#9c9890",
weight: 2,
@@ -82,6 +106,12 @@ export const featureTypes = {
},
flowerBed: {
label: "Flower Bed",
geometryType: "Polygon",
detailFields: {
soil: "string",
mulch: "string",
sunExposure: "string",
},
style: {
color: "#7f7f31",
weight: 2,
@@ -89,18 +119,130 @@ export const featureTypes = {
fillOpacity: 0.38,
},
},
plant: {
label: "Plant",
geometryType: "Point",
detailFields: {
commonName: "string",
genus: "string",
species: "string",
cultivar: "string",
plantedDate: "date",
note: "string",
},
style: {
color: "#3d7140",
weight: 2,
radius: 5,
fillColor: "#78a658",
fillOpacity: 0.8,
},
},
flower: {
label: "Flower",
parentKind: "plant",
geometryType: "Point",
detailFields: {
commonName: "string",
genus: "string",
species: "string",
cultivar: "string",
bloomColor: "string",
bloomSeason: "string",
plantedDate: "date",
note: "string",
},
style: {
color: "#9c3f74",
weight: 2,
radius: 5,
fillColor: "#d979aa",
fillOpacity: 0.85,
},
},
daylily: {
label: "Daylily",
parentKind: "flower",
geometryType: "Point",
detailFields: {
commonName: "string",
genus: "string",
cultivar: "string",
bloomColor: "string",
bloomSeason: "string",
daylilyDatabaseId: "string",
daylilyDatabaseUrl: "url",
plantedDate: "date",
note: "string",
},
externalLinks: [
{
label: "Daylily database",
url: (details) => details.daylilyDatabaseUrl ?? null,
},
],
style: {
color: "#9f5e1d",
weight: 2,
radius: 5,
fillColor: "#f0b44c",
fillOpacity: 0.88,
iconUrl: "./src/assets/icons/daylily.svg",
iconDiameterMeters: 2.5 / 3.280839895,
},
},
shrub: {
label: "Shrub",
parentKind: "plant",
geometryType: "Point",
detailFields: {
commonName: "string",
genus: "string",
species: "string",
cultivar: "string",
canopyDiameterMeters: "number",
heightMeters: "number",
plantedDate: "date",
note: "string",
},
style: (details) => ({
color: "#426a3d",
weight: 1,
radiusMeters: (details.canopyDiameterMeters ?? 1) / 2,
fillColor: "#7e9d58",
fillOpacity: 0.62,
}),
},
tree: {
label: "Tree",
parentKind: "plant",
geometryType: "Point",
detailFields: {
commonName: "string",
genus: "string",
species: "string",
cultivar: "string",
canopyDiameterMeters: "number",
heightMeters: "number",
plantedDate: "date",
note: "string",
},
style: (details) => ({
color: "#2f6b3d",
weight: 2,
radius: clamp(4 + (details.canopyDiameterMeters ?? 2), treeRadiusRange.min, treeRadiusRange.max),
weight: 1,
radiusMeters: (details.canopyDiameterMeters ?? 2) / 2,
fillColor: "#5c9e64",
fillOpacity: 0.85,
fillOpacity: 0.55,
}),
},
sprinkler: {
label: "Sprinkler",
geometryType: "Point",
detailFields: {
zone: "string",
headType: "string",
flowRateGallonsPerMinute: "number",
},
style: {
color: "#2d7dd2",
radius: 5,
@@ -119,7 +261,31 @@ export function getFeatureType(kind) {
return definition;
}
export function listFeatureTypeSchemas() {
return Object.entries(featureTypes).map(([kind, definition]) => ({
kind,
label: definition.label,
parentKind: definition.parentKind ?? null,
geometryType: definition.geometryType,
detailFields: { ...definition.detailFields },
externalLinks: (definition.externalLinks ?? []).map((link) => ({
label: link.label,
})),
}));
}
export function resolveFeatureStyle(kind, details = {}) {
const { style } = getFeatureType(kind);
return typeof style === "function" ? style(details) : style;
}
return typeof style === "function" ? style(details) : { ...style };
}
export function resolveFeatureLinks(kind, details = {}) {
const { externalLinks = [] } = getFeatureType(kind);
return externalLinks
.map((link) => ({
label: link.label,
url: link.url(details),
}))
.filter((link) => link.url);
}