Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,15 @@
"WHERE_TRANSPLANT_LOCATION": "Where will you transplant to?",
"WILD_CROP": "Are you harvesting a wild crop?"
},
"MARKET_DIRECTORY": {
"COMPLETE_PROFILE": "Complete your profile below to get started and promote your products. You only need to go through this process once. You can update your shared data and opt out any time.",
"GET_LISTED": "Get your farm listed in trusted directories",
"CONSENT": {
"TITLE": "Consent",
"MISSING_DETAILS": "You’re almost ready to publish! Just fill in the missing details in your Market directory info form above first."
},
"MARKET_DIRECTORY_INFO": "Market directory info"
},
"MENU": {
"ACTUAL_REVENUES": "Actual revenues",
"ANIMALS": "Animals",
Expand Down
4 changes: 4 additions & 0 deletions packages/webapp/src/assets/images/check-complete.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/webapp/src/assets/images/check-incomplete.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2025 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { TFunction, useTranslation } from 'react-i18next';
import clsx from 'clsx';
import styles from './styles.module.scss';

interface MarketDirectoryConsentProps {
disabled: boolean;
}

const MarketDirectoryConsent = ({ disabled }: MarketDirectoryConsentProps) => {
const { t } = useTranslation();
// LF-5016 -- RTK Query setup for Market Directories here

return (
<div className={styles.consentContainer}>
<h3 className={styles.consentTitle}>{t('MARKET_DIRECTORY.CONSENT.TITLE')}</h3>
{disabled && <WarningBanner t={t} />}
{/* LF-5016 -- replace with actual Pure Component */}
<div className={clsx(styles.marketTiles, disabled && styles.disabled)}>
<div />
<div />
<div />
</div>
</div>
);
};

export default MarketDirectoryConsent;

const WarningBanner = ({ t }: { t: TFunction }) => {
return (
<div className={styles.warningBanner}>
<p>{t('MARKET_DIRECTORY.CONSENT.MISSING_DETAILS')}</p>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2025 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

@import '@assets/mixin.scss';

.consentContainer {
width: 100%;
display: flex;
padding-inline: 24px;
flex-direction: column;
gap: 16px;

.consentTitle {
color: var(--Colors-Neutral-Neutral-900);
}

@include xs-breakpoint {
padding-inline: 0;
}
}

.warningBanner {
padding: 8px 16px;
display: flex;
justify-content: center;

border-radius: 4px;
background: var(--Colors-Accent---singles-Red-light);
border: 1px solid var(--Colors-Accent---singles-Red-light);

color: var(--Colors-Accent---singles-Red-dark);
font-style: italic;
font-size: 16px;
font-weight: 700;
}

/*------------------
Placeholder styles -- remove in LF-5016 */
.marketTiles {
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 32px;
padding: 32px;

div {
background-color: var(--Colors-Accent---singles-Purple-light);
height: 100px;
border-radius: 8px;
}

&.disabled {
div {
background-color: var(--Colors-Neutral-Neutral-100);
}
}

@include xs-breakpoint {
padding: 16px;
gap: 16px;
}
}
/*------------------*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2025 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import styles from './styles.module.scss';

interface MarketDirectoryInfoFormProps {
setIsComplete: (isComplete: boolean) => void;
isComplete?: boolean;
close: () => void;
}

const MarketDirectoryInfoForm = ({
setIsComplete,
isComplete,
close,
}: MarketDirectoryInfoFormProps) => {
// LF-4990 -- RTK Query setup for Market Directory Data here

return (
<div>
{/* LF-4990 -- replace with actual Pure Form Component */}
<label className={styles.checkboxLabel}>
Complete Form
<input
type="checkbox"
checked={isComplete}
onChange={(e) => {
setIsComplete(e.target.checked);
if (e.target.checked) {
close();
}
}}
/>
</label>
</div>
);
};

export default MarketDirectoryInfoForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2025 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

/*------------------
Placeholder styles -- remove in LF-4990 */
.checkboxLabel {
font-size: 16px;
font-weight: 700;
padding: 32px;
display: flex;
gap: 8px;
width: 100%;
}
/*------------------*/
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,121 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { TFunction, useTranslation } from 'react-i18next';
import clsx from 'clsx';
import styles from './styles.module.scss';
import CardLayout from '../../../../components/Layout/CardLayout';
import { useFarmSettingsRouterTabs } from '../useFarmSettingsRouterTabs';
import RouterTab from '../../../../components/RouterTab';
import { Variant as TabVariants } from '../../../../components/RouterTab/Tab';
import ExpandableItem from '../../../../components/Expandable/ExpandableItem';
import useExpandable from '../../../../components/Expandable/useExpandableItem';
import { ReactComponent as CheckComplete } from '../../../../assets/images/check-complete.svg';
import { ReactComponent as CheckIncomplete } from '../../../../assets/images/check-incomplete.svg';
import MarketDirectoryInfoForm from './InfoForm';
import MarketDirectoryConsent from './Consent';

enum FormCards {
INFO,
}

const MarketDirectory = () => {
const history = useHistory();

const routerTabs = useFarmSettingsRouterTabs();
const { t } = useTranslation();

const { expandedIds, toggleExpanded, unExpand } = useExpandable({ isSingleExpandable: true });

const [completionStatus, setCompletionStatus] = useState<Record<FormCards, boolean>>({
[FormCards.INFO]: false,
});

const updateCompletionStatus = (formKey: FormCards, isComplete: boolean) => {
setCompletionStatus((prev) => ({
...prev,
[formKey]: isComplete,
}));
};

const areAllFormsComplete = Object.values(completionStatus).every(Boolean);

const formCards = [
{
key: FormCards.INFO,
title: t('MARKET_DIRECTORY.MARKET_DIRECTORY_INFO'),
content: (
<MarketDirectoryInfoForm
isComplete={completionStatus[FormCards.INFO]}
setIsComplete={(isComplete) => updateCompletionStatus(FormCards.INFO, isComplete)}
close={() => unExpand(FormCards.INFO)}
/>
),
},
];

return (
<CardLayout>
<RouterTab tabs={routerTabs} variant={TabVariants.UNDERLINE} history={history} />
<h3>
<i>Coming soon!</i>
</h3>

<div className={styles.container}>
<DirectoryCallout t={t} />

{formCards.map(({ key, title, content }) => {
const isExpanded = expandedIds.includes(key);

return (
<div key={key} className={clsx(styles.formCard, isExpanded && styles.expanded)}>
<ExpandableItem
itemKey={key}
isExpanded={isExpanded}
onClick={() => toggleExpanded(key)}
mainContent={
<ExpandableHeader
title={title}
isExpanded={isExpanded}
isComplete={completionStatus[key]}
/>
}
expandedContent={content}
leftCollapseIcon
iconClickOnly={false}
/>
</div>
);
})}

<MarketDirectoryConsent disabled={!areAllFormsComplete} />
</div>
</CardLayout>
);
};

export default MarketDirectory;

const DirectoryCallout = ({ t }: { t: TFunction }) => {
return (
<div className={styles.callout}>
<h4 className={styles.calloutTitle}>{t('MARKET_DIRECTORY.GET_LISTED')}</h4>
<p>{t('MARKET_DIRECTORY.COMPLETE_PROFILE')}</p>
</div>
);
};

const ExpandableHeader = ({
title,
isExpanded,
isComplete,
}: {
title: string;
isExpanded: boolean;
isComplete: boolean;
}) => {
return (
<div className={clsx(styles.expandableHeader, isExpanded && styles.expanded)}>
<p>{title}</p>
{isComplete ? <CheckComplete /> : <CheckIncomplete />}
</div>
);
};
Loading
Loading