From cc04945c401eccca22eedad0807f10999504a5e5 Mon Sep 17 00:00:00 2001 From: frozenhelium Date: Sun, 7 Jun 2026 14:29:16 +0545 Subject: [PATCH] feat(new-project): add project availability info --- app/views/NewProject/index.tsx | 121 +++++++++++++++++-------- app/views/NewProject/styles.module.css | 14 +++ 2 files changed, 97 insertions(+), 38 deletions(-) create mode 100644 app/views/NewProject/styles.module.css diff --git a/app/views/NewProject/index.tsx b/app/views/NewProject/index.tsx index 190df09..3633a41 100644 --- a/app/views/NewProject/index.tsx +++ b/app/views/NewProject/index.tsx @@ -4,6 +4,11 @@ import { useMemo, } from 'react'; import { MdArrowForward } from 'react-icons/md'; +import { + PiCheckCircleDuotone, + PiInfoDuotone, + PiXCircleDuotone, +} from 'react-icons/pi'; import { generatePath, useNavigate, @@ -24,7 +29,6 @@ import { ulid } from 'ulid'; import { gql } from 'urql'; import routes from '#base/configs/routes'; -import Alert from '#components/Alert'; import Button from '#components/Button'; import Container from '#components/Container'; import Description from '#components/Description'; @@ -54,6 +58,8 @@ import { DeepNonNullable } from '#utils/types'; import ProjectGeneralInputs from './ProjectGeneralInputs'; +import styles from './styles.module.css'; + // eslint-disable-next-line @typescript-eslint/no-unused-vars const CREATE_PROJECT_MUTATION = gql` ${OPERATION_INFO_FRAGMENT} @@ -123,48 +129,80 @@ function projectTypeLabelSelector(value: AppEnumCollectionProjectTypeEnum) { ); } -const projectTypeDescriptions: Record = { +const projectTypeDescriptions: Record = { [ProjectTypeEnum.Find]: 'Swipe through satellite images to identify & select those that contain the requested features such as buildings, roadways, waterways and more.', [ProjectTypeEnum.Compare]: 'Review before and after satellite images to detect changes in the environment that help inform damage assessment, climate change, or inaccurate data.', [ProjectTypeEnum.Validate]: 'Assess building footprints for accuracy where buildings have been previously traced by remote mappers or through AI to identify where remapping is needed.', [ProjectTypeEnum.ValidateImage]: 'Assess how well machine learning detections match real-world features in images, flagging false or inaccurate results. This helps improve model accuracy and dataset quality, supporting better outcomes for social good applications.', - [ProjectTypeEnum.Completeness]: ( - -
- Assess how well OSM data represents buildings in satellite imagery, - flagging areas where mapping is incomplete. - This helps identify areas needing further mapping efforts to enhance - OSM's accuracy, especially for disaster response and risk assessment. -
- -
- ), - [ProjectTypeEnum.Street]: ( - -
- Explore ground-level images to find relevant features and - capture more detailed information on communities. -
- -
- ), - [ProjectTypeEnum.Locate]: 'Locate objects', + [ProjectTypeEnum.Completeness]: 'Assess how well OSM data represents buildings in satellite imagery, flagging areas where mapping is incomplete. This helps identify areas needing further mapping efforts to enhance OSM\'s accuracy, especially for disaster response and risk assessment.', + [ProjectTypeEnum.Street]: 'Explore ground-level images to find relevant features and capture more detailed information on communities.', + [ProjectTypeEnum.Locate]: 'Mark the subgrid cells within satellite image tiles that contain requested features such as rooftops, solar panels, or trees, helping train machine learning models to localize features more accurately.', +}; + +interface ProjectTypeAvailability { + mobile: boolean; + web: boolean; + caveat?: string; +} + +const projectTypeAvailability: Record = { + [ProjectTypeEnum.Find]: { mobile: true, web: true }, + [ProjectTypeEnum.Compare]: { mobile: true, web: true }, + [ProjectTypeEnum.Validate]: { mobile: true, web: true }, + [ProjectTypeEnum.ValidateImage]: { mobile: true, web: true }, + [ProjectTypeEnum.Completeness]: { + mobile: true, + web: true, + caveat: 'Vector overlay layer is not supported in the mobile app', + }, + [ProjectTypeEnum.Street]: { mobile: false, web: true }, + [ProjectTypeEnum.Locate]: { mobile: true, web: true }, }; +interface ProjectTypeAvailabilityOutputProps { + availability: ProjectTypeAvailability; +} + +function ProjectTypeAvailabilityOutput(props: ProjectTypeAvailabilityOutputProps) { + const { availability } = props; + + const platforms = [ + { label: 'Mobile app', available: availability.mobile }, + { label: 'Web app', available: availability.web }, + ]; + + return ( + + {platforms.map((platform) => ( + + ) : ( + + )} + > + {platform.label} + + ))} + {isDefined(availability.caveat) && ( + } + > + {availability.caveat} + + )} + + ); +} + function NewProject() { const navigate = useNavigate(); const alert = useAlert(); @@ -334,7 +372,14 @@ function NewProject() { /> {isDefined(value.projectType) && ( - {projectTypeDescriptions[value.projectType]} + +
+ {projectTypeDescriptions[value.projectType]} +
+ +
)} diff --git a/app/views/NewProject/styles.module.css b/app/views/NewProject/styles.module.css new file mode 100644 index 0000000..b7b13a5 --- /dev/null +++ b/app/views/NewProject/styles.module.css @@ -0,0 +1,14 @@ +.available-icon { + color: var(--color-success); + font-size: var(--font-size-lg); +} + +.unavailable-icon { + color: var(--color-danger); + font-size: var(--font-size-lg); +} + +.caveat-icon { + color: var(--color-accent); + font-size: var(--font-size-lg); +}