diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..9a535f8d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,105 @@ +# GoodCollective Monorepo – AI Agent Reference + +## Monorepo Layout + +| Path | Description | +| ------------------- | -------------------------------------------------------------- | +| packages/contracts/ | Hardhat Solidity contracts: pool factories, pools, ProvableNFT | +| packages/sdk-js/ | TypeScript SDK: wraps contracts, loads from deployment.json | +| packages/app/ | React Native Web app using NativeBase, G$ support | +| packages/subgraph/ | TheGraph schema and mappings: pools, claims | +| packages/services/ | Docker setup for devnet/Subgraph infra | +| releases/ | deployment.json: contract addresses by network | +| scripts/ | Utility scripts (migrations, transforms) | +| test/ | Cross-package integration tests | + +## Smart Contracts - Essential Concepts + +- **DirectPaymentsFactory & DirectPaymentsPool** + + - Factory deploys pools; links each to a ProvableNFT. + - Uses a UUPS proxy. Updates via `updateImpl`. + - Holds/verifies pool metadata (IPFS). + - Minting NFT triggers reward distribution (optional on mint). + +- **UBIPool & UBIPoolFactory** + + - Creates and manages UBI pools by project ID. + - Uses UpgradeableBeacon (`updateImpl` affects all). + - Tracks which pool controls a project. + - Small fee (bps) sent to feeRecipient. + +- **ProvableNFT** + + - ERC-721 (UUPS) for proof-of-action NFTs (linked per pool). + - `mintNFT` may also trigger reward claim. + +- **GoodDollar Integration** + - **G$ Token:** All rewards in GoodDollar (ISuperToken). + - **feeRecipient:** Defaults to GoodDollar UBIScheme if available. + +## SDK Usage: Always Prefer these Methods! + +**Do NOT hardcode contract addresses.** Use the SDK, which loads addresses and ABIs from deployment.json by chainId. + +### Key SDK Methods + +- `sdk.createPool(...)` – Deploy DirectPaymentsPool via factory. +- `sdk.mintNft(...)` – Mint/generate proof-of-action NFT (optionally claim reward). +- `sdk.supportFlow(...)` – Start Superfluid G$ stream to a pool. +- `sdk.supportSingleTransferAndCall(...)` – One-time donation via ERC677. +- `sdk.supportSingleBatch(...)` – Batch donation via Superfluid. + +**Best Practice:** +Let the SDK resolve all addresses. Always load addresses/ABIs by network via the SDK. + +## App UI Coding Guide + +**Always prefer NativeBase for UI in `packages/app`!** + +- Use ``, ``, ``, etc. +- Style using NativeBase props (e.g. `p={4}`, `bg="goodPurple.400"`). +- Use theme variables (see `app/src/theme`). +- Avoid `StyleSheet.create` for new components; use prop-based styling. +- If necessary, compute style objects _and spread into NativeBase components_. + +**Example:** + +```tsx + + + ... + + +``` + +- Responsive props (`w={8} h={8}` etc.) preferred over fixed styles. + +## Testing & Workflow + +1. **Deploy Local Contracts:** + `yarn test:setup` (sets up contracts, generates latest deployment.json) + +2. **Run Tests:** + `yarn test` (executes contract & SDK tests; all must pass) + +3. **Lint & Format:** + Follow Prettier/ESLint (2-space, single quotes, <=120 chars). + Make sure typescript compiles by running `tsc` in the affected packages or apps. + +4. **Build related packages/apps** + Run build script for the affected package or app. + +5. **Pull Requests:** + - Clear description of changes. + - All tests AND lint must pass. + +## Agent Coding Principles + +- Use SDK for all contract interactions. +- Never hardcode contract addresses; always resolve via deployment.json. +- Style React components with NativeBase/theming, not CSS or StyleSheet for new code. +- Follow existing conventions for file locations, imports, and naming. +- Ensure all relevant tests pass after changes. + +--- diff --git a/packages/app/src/components/ActivityLog.tsx b/packages/app/src/components/ActivityLog.tsx index aa5e1c0f..b7fc0a35 100644 --- a/packages/app/src/components/ActivityLog.tsx +++ b/packages/app/src/components/ActivityLog.tsx @@ -1,6 +1,5 @@ -import { Image, Text, View, StyleSheet } from 'react-native'; +import { Image, Text, View } from 'native-base'; import { InterRegular, InterSemiBold } from '../utils/webFonts'; -import { Colors } from '../utils/colors'; const ReceiveIconUri = `data:image/svg+xml;utf8, `; @@ -28,10 +27,10 @@ function ActivityLog({}: ActivityLogProps) { ); } -const styles = StyleSheet.create({ +const styles = { container: { width: '100%', - backgroundColor: Colors.white, + backgroundColor: 'white', paddingLeft: 16, paddingRight: 16, }, @@ -40,10 +39,10 @@ const styles = StyleSheet.create({ flex: 1, flexDirection: 'row', gap: 8, - backgroundColor: Colors.white, + backgroundColor: 'white', }, bar: { - backgroundColor: Colors.green[100], + backgroundColor: 'goodGreen.200', width: 6, height: 40, alignSelf: 'flex-start', @@ -53,14 +52,14 @@ const styles = StyleSheet.create({ height: 32, }, name: { - color: Colors.black, + color: 'black', fontSize: 16, lineHeight: 24, ...InterSemiBold, width: '100%', }, date: { - color: Colors.gray[100], + color: 'goodGrey.400', fontSize: 14, lineHeight: 21, textAlign: 'left', @@ -74,5 +73,5 @@ const styles = StyleSheet.create({ }, logProfileDetails: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, logDate: { alignItems: 'flex-end' }, -}); +} as const; export default ActivityLog; diff --git a/packages/app/src/components/BannerPool.tsx b/packages/app/src/components/BannerPool.tsx index 5df380a1..bf5ad962 100644 --- a/packages/app/src/components/BannerPool.tsx +++ b/packages/app/src/components/BannerPool.tsx @@ -1,6 +1,5 @@ -import { Image, Linking, StyleSheet, TouchableOpacity } from 'react-native'; -import { View } from 'native-base'; -import { Colors } from '../utils/colors'; +import { Linking } from 'react-native'; +import { Image, Pressable, View } from 'native-base'; import { DirectPayments, Segmented, Community } from '../assets/poolTypes'; const getPoolType = (pool: string) => { @@ -26,30 +25,28 @@ function BannerPool({ poolType: string; }) { const poolTypes = getPoolType(poolType); + const imgStyles = !homePage ? (isDesktopView ? styles.imageDesktop : styles.image) : styles.sectionImage; return ( - - - + header + { e.stopPropagation(); Linking.openURL('https://www.gooddollar.org/goodcollective-how-it-work'); }}> - - + + pool - + ); } -const styles = StyleSheet.create({ +const styles = { sectionImage: { resizeMode: 'cover', height: 192, - backgroundColor: Colors.white, + backgroundColor: 'white', borderTopLeftRadius: 20, borderTopRightRadius: 20, }, @@ -80,13 +77,13 @@ const styles = StyleSheet.create({ right: 12, padding: 5, cursor: 'pointer', - backgroundColor: '#ffffff', + backgroundColor: 'white', borderRadius: 8, }, poolTypeImg: { width: '100%', height: '100%', }, -}); +} as const; export default BannerPool; diff --git a/packages/app/src/components/CollectiveHomeCard.tsx b/packages/app/src/components/CollectiveHomeCard.tsx index def3beb0..5391aa39 100644 --- a/packages/app/src/components/CollectiveHomeCard.tsx +++ b/packages/app/src/components/CollectiveHomeCard.tsx @@ -1,8 +1,7 @@ -import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import { Pressable, Text, View } from 'native-base'; import { InterSemiBold, InterSmall } from '../utils/webFonts'; import useCrossNavigate from '../routes/useCrossNavigate'; -import { Colors } from '../utils/colors'; import { Ocean } from '../assets'; import { useScreenSize } from '../theme/hooks'; import BannerPool from './BannerPool'; @@ -21,29 +20,29 @@ function CollectiveHomeCard({ name, description, headerImage, route, poolType }: const headerImg = headerImage ? { uri: headerImage } : Ocean; + const containerStyle = { + ...styles.cardContainer, + ...styles.elevation, + ...(isDesktopView ? styles.cardContainerDesktop : {}), + ...(isTabletView ? { marginBottom: 20 } : {}), + }; + return ( - navigate(`/collective/${route}`)}> + navigate(`/collective/${route}`)}> {name} {description} - + ); } -const styles = StyleSheet.create({ +const styles = { cardContainer: { width: '100%', minHeight: 330, - backgroundColor: Colors.white, + backgroundColor: 'white', paddingTop: 0, borderRadius: 20, marginBottom: 20, @@ -65,7 +64,7 @@ const styles = StyleSheet.create({ marginTop: 8, fontSize: 16, fontWeight: '400', - color: Colors.gray[100], + color: 'goodGrey.400', ...InterSmall, lineHeight: 24, maxHeight: 'auto', @@ -74,7 +73,7 @@ const styles = StyleSheet.create({ sectionImage: { resizeMode: 'cover', height: 192, - backgroundColor: Colors.white, + backgroundColor: 'white', borderTopLeftRadius: 20, borderTopRightRadius: 20, }, @@ -84,7 +83,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 12, }, elevation: { - shadowColor: Colors.black, + shadowColor: 'black', shadowOffset: { width: 0, height: 12, @@ -93,6 +92,6 @@ const styles = StyleSheet.create({ shadowRadius: 15, elevation: 24, }, -}); +} as const; export default CollectiveHomeCard; diff --git a/packages/app/src/components/DonorsList/DonorsList.tsx b/packages/app/src/components/DonorsList/DonorsList.tsx index 26f8d01a..925fa0ce 100644 --- a/packages/app/src/components/DonorsList/DonorsList.tsx +++ b/packages/app/src/components/DonorsList/DonorsList.tsx @@ -1,4 +1,5 @@ -import { Platform, StyleSheet, View } from 'react-native'; +import { Platform } from 'react-native'; +import { View } from 'native-base'; import { DonorCollective } from '../../models/models'; import { DonorsListItem } from './DonorsListItem'; import { useMemo } from 'react'; @@ -22,7 +23,7 @@ function DonorsList({ donors, listStyle }: DonorsListProps) { const userFullNames = useFetchFullNames(userAddresses); return ( - + {sortedDonors.map((donor, index) => ( ))} @@ -30,7 +31,7 @@ function DonorsList({ donors, listStyle }: DonorsListProps) { ); } -const styles = StyleSheet.create({ +const styles = { donorsListContainer: { width: '100%' }, list: { width: '100%', @@ -41,6 +42,6 @@ const styles = StyleSheet.create({ default: 'auto', }), }, -}); +} as const; export default DonorsList; diff --git a/packages/app/src/components/DonorsList/DonorsListItem.tsx b/packages/app/src/components/DonorsList/DonorsListItem.tsx index c7b26eb4..8d374b50 100644 --- a/packages/app/src/components/DonorsList/DonorsListItem.tsx +++ b/packages/app/src/components/DonorsList/DonorsListItem.tsx @@ -1,6 +1,4 @@ -import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; -import { Colors } from '../../utils/colors'; -import { InterRegular, InterSemiBold } from '../../utils/webFonts'; +import { Text, Pressable, View } from 'native-base'; import { DonorCollective } from '../../models/models'; import useCrossNavigate from '../../routes/useCrossNavigate'; import { formatAddress } from '../../lib/formatAddress'; @@ -23,27 +21,31 @@ export const DonorsListItem = ({ donor, rank, userFullName }: DonorsListItemProp const userIdentifier = userFullName ?? ensName ?? formatAddress(donor.donor); const circleBackgroundColor = - rank === 1 ? Colors.yellow[100] : rank === 2 ? Colors.gray[700] : rank === 3 ? Colors.orange[400] : 'none'; + rank === 1 ? 'goodYellow.100' : rank === 2 ? 'goodGrey.700' : rank === 3 ? 'goodOrange.350' : 'none'; const circleTextColor = - rank === 1 ? Colors.yellow[200] : rank === 2 ? Colors.blue[200] : rank === 3 ? Colors.brown[100] : Colors.black; + rank === 1 ? 'goodYellow.200' : rank === 2 ? 'goodBlue.200' : rank === 3 ? 'goodBrown.100' : 'black'; return ( - navigate(`/profile/${donor.donor}`)}> - - - {rank} + navigate(`/profile/${donor.donor}`)}> + + + + {rank} + - {userIdentifier} + + {userIdentifier} + - - G$ + + G$ - + ); }; -const styles = StyleSheet.create({ +const styles = { circle: { paddingVertical: 2, paddingHorizontal: 10, @@ -52,17 +54,17 @@ const styles = StyleSheet.create({ circleText: { lineHeight: 24, fontSize: 16, - ...InterRegular, + fontWeight: 500, }, rowNumber: { fontSize: 16, lineHeight: 24, - color: Colors.black, - ...InterRegular, + color: 'black', + fontWeight: 500, }, rowBetween: { width: '100%', - backgroundColor: Colors.white, + backgroundColor: 'white', flex: 1, flexDirection: 'row', marginVertical: 8, @@ -77,7 +79,7 @@ const styles = StyleSheet.create({ row: { minHeight: 48, width: '100%', - backgroundColor: Colors.white, + backgroundColor: 'white', flex: 1, flexDirection: 'row', marginVertical: 8, @@ -85,19 +87,19 @@ const styles = StyleSheet.create({ }, title: { fontSize: 16, - ...InterSemiBold, + fontWeight: 700, width: '100%', - color: Colors.black, + color: 'black', marginLeft: 8, }, totalDonated: { fontSize: 14, - ...InterRegular, + fontWeight: 500, textAlign: 'right', width: '100%', - color: Colors.gray[100], + color: 'goodGrey.400', }, currency: { - ...InterSemiBold, + fontWeight: 700, }, -}); +} as const; diff --git a/packages/app/src/components/Dropdown.tsx b/packages/app/src/components/Dropdown.tsx index ae57425c..d865280c 100644 --- a/packages/app/src/components/Dropdown.tsx +++ b/packages/app/src/components/Dropdown.tsx @@ -1,8 +1,7 @@ -import { Image, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import { Platform } from 'react-native'; +import { HStack, Pressable, Image, Text, View } from 'native-base'; import { useState } from 'react'; -import { HStack, Pressable } from 'native-base'; -import { Colors } from '../utils/colors'; import { InterSemiBold, InterSmall } from '../utils/webFonts'; import { chevronDown } from '../assets'; @@ -43,7 +42,7 @@ const Dropdown = ({ onSelect, value, options }: DropdownProps) => { {open ? ( {options.map((option) => ( - { @@ -51,7 +50,7 @@ const Dropdown = ({ onSelect, value, options }: DropdownProps) => { setOpen(false); }}> {renderDropdownItemText(value, option.label)} - + ))} ) : null} @@ -59,9 +58,9 @@ const Dropdown = ({ onSelect, value, options }: DropdownProps) => { ); }; -const styles = StyleSheet.create({ +const styles = { buttonText: { - color: Colors.purple[400], + color: 'goodPurple.500', fontSize: 18, lineHeight: 27, ...InterSemiBold, @@ -79,7 +78,7 @@ const styles = StyleSheet.create({ native: 'scroll', default: 'auto', }), - backgroundColor: Colors.white, + backgroundColor: 'white', paddingTop: 10, paddingBottom: 10, position: 'absolute', @@ -87,7 +86,7 @@ const styles = StyleSheet.create({ top: 50, left: 0, borderRadius: 12, - shadowColor: Colors.black, + shadowColor: 'black', shadowOffset: { width: 0, height: 12, @@ -107,14 +106,14 @@ const styles = StyleSheet.create({ dropdownMyProfileText: { fontSize: 18, marginLeft: 15, - color: Colors.purple[400], + color: 'goodPurple.500', }, dropdownText: { ...InterSmall, fontSize: 14, - color: Colors.purple[400], + color: 'goodPurple.500', textAlign: 'center', }, -}); +} as const; export default Dropdown; diff --git a/packages/app/src/components/FlowingDonationsRowItem.tsx b/packages/app/src/components/FlowingDonationsRowItem.tsx index 5880985d..7df38091 100644 --- a/packages/app/src/components/FlowingDonationsRowItem.tsx +++ b/packages/app/src/components/FlowingDonationsRowItem.tsx @@ -1,8 +1,7 @@ -import { Image, Text, View, StyleSheet } from 'react-native'; +import { Image, Text, View } from 'native-base'; import Decimal from 'decimal.js'; import { InterRegular, InterSemiBold } from '../utils/webFonts'; -import { Colors } from '../utils/colors'; import { useScreenSize } from '../theme/hooks'; import { useDonorCollectivesFlowingBalancesWithAltStaticBalance } from '../hooks/useFlowingBalance'; @@ -45,33 +44,33 @@ function FlowingDonationsRowItem({ ); return ( - - - - {rowInfo} + + + icon + {rowInfo} - + {token.symbol}{' '} - {isDesktopView && currency && = {usdValueCurrentPool} USD} + {isDesktopView && currency && = {usdValueCurrentPool} USD} - {!isDesktopView && currency && = {usdValueCurrentPool} USD} + {!isDesktopView && currency && = {usdValueCurrentPool} USD} ); } -const styles = StyleSheet.create({ +const styles = { row: { width: '100%', - backgroundColor: Colors.white, + backgroundColor: 'white', flex: 1, flexDirection: 'row', alignItems: 'center', @@ -91,7 +90,7 @@ const styles = StyleSheet.create({ maxWidth: '60%', fontWeight: '700', fontSize: 16, - color: Colors.black, + color: 'black', ...InterSemiBold, }, rightItem: { @@ -99,7 +98,7 @@ const styles = StyleSheet.create({ alignSelf: 'flex-end', }, rowData: { - color: Colors.gray[100], + color: 'goodGrey.400', textAlign: 'right', fontSize: 16, ...InterSemiBold, @@ -108,9 +107,9 @@ const styles = StyleSheet.create({ rowBalance: { fontSize: 12, textAlign: 'right', - color: Colors.gray[200], + color: 'goodGrey.25', ...InterRegular, }, -}); +} as const; export default FlowingDonationsRowItem; diff --git a/packages/app/src/components/Header/Header.tsx b/packages/app/src/components/Header/Header.tsx index c62f9a87..a90cc2dd 100644 --- a/packages/app/src/components/Header/Header.tsx +++ b/packages/app/src/components/Header/Header.tsx @@ -1,11 +1,10 @@ -import { Image, StyleSheet, TouchableOpacity, View } from 'react-native'; +import { Image, Pressable, View } from 'native-base'; import { useAccount } from 'wagmi'; import { ConnectedAccountDisplay } from './ConnectedAccountDisplay'; import { ConnectWalletMenu } from './ConnectWalletMenu'; import { DropdownMenu } from './DropdownMenu'; import useCrossNavigate from '../../routes/useCrossNavigate'; -import { Colors } from '../../utils/colors'; import { BackIcon, HeaderLogo } from '../../assets'; import { useScreenSize } from '../../theme/hooks'; @@ -15,15 +14,20 @@ function Header(): JSX.Element { const { navigate } = useCrossNavigate(); return ( - + {isDesktopView && ( - - - navigate('/')}> - - + + + navigate('/')}> + logo + - + {address && } {!address && } )} {!isDesktopView && ( - - + + {address && } {!address && } - - navigate(-1)}> - - - + + navigate(-1)}> + back + + @@ -59,10 +63,10 @@ function Header(): JSX.Element { ); } -const styles = StyleSheet.create({ +const styles = { headerMobileContainer: { height: 105, - backgroundColor: Colors.blue[100], + backgroundColor: 'goodPurple.300', paddingTop: 10, paddingBottom: 10, paddingLeft: 20, @@ -109,6 +113,6 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', flexDirection: 'row', }, -}); +} as const; export default Header; diff --git a/packages/app/src/components/ImpactButton.tsx b/packages/app/src/components/ImpactButton.tsx index 7ae280c9..d90f0277 100644 --- a/packages/app/src/components/ImpactButton.tsx +++ b/packages/app/src/components/ImpactButton.tsx @@ -1,7 +1,7 @@ -import { Image, Platform, Text, TouchableOpacity, View, StyleSheet } from 'react-native'; +import { Platform } from 'react-native'; +import { Image, Pressable, Text, View } from 'native-base'; import { InterSemiBold } from '../utils/webFonts'; -import { Colors } from '../utils/colors'; import { chevronRight } from '../assets'; import { useScreenSize } from '../theme/hooks'; @@ -14,27 +14,28 @@ function ImpactButton({ title, onClick }: ImpactButtonProps) { const { isDesktopView } = useScreenSize(); return ( - - - {title} - + + {title} + icon - + ); } -const styles = StyleSheet.create({ +const styles = { button: { width: '100%', height: 56, - backgroundColor: Colors.purple[200], - color: Colors.purple[100], + backgroundColor: 'goodPurple.400', + color: 'goodPurple.100', position: 'absolute', bottom: 0, paddingVertical: 8, @@ -57,7 +58,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, buttonText: { - color: Colors.purple[100], + color: 'goodPurple.100', fontSize: 18, ...InterSemiBold, lineHeight: 27, @@ -66,8 +67,8 @@ const styles = StyleSheet.create({ icon: { width: 24, height: 24, - color: Colors.black, + color: 'black', }, -}); +} as const; export default ImpactButton; diff --git a/packages/app/src/components/Layout/Breadcrumb.tsx b/packages/app/src/components/Layout/Breadcrumb.tsx index d6d7ebf1..68a0aa96 100644 --- a/packages/app/src/components/Layout/Breadcrumb.tsx +++ b/packages/app/src/components/Layout/Breadcrumb.tsx @@ -1,5 +1,4 @@ -import { Image, StyleSheet, Text, TouchableOpacity } from 'react-native'; -import { Colors } from '../../utils/colors'; +import { Image, Pressable, Text } from 'native-base'; import { useNavigate } from 'react-router-dom'; import { chevronRight } from '../../assets'; @@ -18,41 +17,41 @@ function Breadcrumb({ path }: BreadcrumbProps) { const onClickHome = () => navigate('/'); return ( - - - - - + + + back + + GoodCollective Home {path.map((entry, index) => ( navigate(entry.route)}> {` / ${entry.text}`} ))} - + ); } -const styles = StyleSheet.create({ +const styles = { container: { height: 24, alignItems: 'center', flexDirection: 'row', marginBottom: 12, }, - previousPage: { color: Colors.purple[200] }, - activePage: { color: Colors.gray[200] }, + previousPage: { color: 'goodPurple.400' }, + activePage: { color: 'goodGrey.25' }, backIcon: { width: 20, height: 20, marginRight: 10, transform: [{ rotate: '180deg' }], - tintColor: Colors.purple[400], + tintColor: 'goodPurple.500', }, -}); +} as const; export default Breadcrumb; diff --git a/packages/app/src/components/ProfileView.tsx b/packages/app/src/components/ProfileView.tsx index 67ae2497..45335269 100644 --- a/packages/app/src/components/ProfileView.tsx +++ b/packages/app/src/components/ProfileView.tsx @@ -1,6 +1,5 @@ -import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native'; +import { Text, View, Image, Pressable } from 'native-base'; import { InterSemiBold, InterSmall } from '../utils/webFonts'; -import { Colors } from '../utils/colors'; import { Link } from 'native-base'; import { VerifiedIcon } from '../assets'; import env from '../lib/env'; @@ -21,7 +20,7 @@ function ProfileView({ firstName, lastName, ensDomain, userAddress, isWhiteliste const secondary = firstName ? ensDomain ?? formattedAddress : ensDomain ? formattedAddress : undefined; return ( - + { @@ -33,23 +32,23 @@ function ProfileView({ firstName, lastName, ensDomain, userAddress, isWhiteliste } - + ); } -const styles = StyleSheet.create({ +const styles = { pfp: { width: 64, height: 64, - backgroundColor: Colors.white, + backgroundColor: 'white', borderRadius: 32, }, profileView: { width: '100%', height: 80, minHeight: 80, - backgroundColor: Colors.gray[400], + backgroundColor: 'goodGrey.100', flex: 1, flexDirection: 'row', paddingHorizontal: 8, @@ -63,7 +62,7 @@ const styles = StyleSheet.create({ gap: 4, }, line: { - color: Colors.gray[100], + color: 'goodGrey.400', fontSize: 16, ...InterSmall, }, @@ -75,6 +74,6 @@ const styles = StyleSheet.create({ height: 16, width: 16, }, -}); +} as const; export default ProfileView; diff --git a/packages/app/src/components/RowItem.tsx b/packages/app/src/components/RowItem.tsx index 1ef4713a..f2ce6519 100644 --- a/packages/app/src/components/RowItem.tsx +++ b/packages/app/src/components/RowItem.tsx @@ -1,7 +1,6 @@ -import { Image, Text, View, StyleSheet } from 'react-native'; +import { Image, Text, View } from 'native-base'; import { InterRegular, InterSemiBold } from '../utils/webFonts'; -import { Colors } from '../utils/colors'; import { useScreenSize } from '../theme/hooks'; import { formatFiatCurrency } from '../lib/formatFiatCurrency'; @@ -21,36 +20,36 @@ function RowItem({ rowInfo, rowData, balance, currency, imageUrl }: RowItemProps const usdBalance = balance ? formatFiatCurrency(balance) : '0.00'; return ( - - - - {rowInfo} + + + icon + {rowInfo} - {!currency && {rowData}} + {!currency && {rowData}} {currency ? ( - {currency} + {currency} - {isDesktopView ? = {usdBalance} USD : null} + {isDesktopView ? = {usdBalance} USD : null} ) : null} - {!isDesktopView && currency ? = {usdBalance} USD : null} + {!isDesktopView && currency ? = {usdBalance} USD : null} ); } -const styles = StyleSheet.create({ +const styles = { row: { width: '100%', - backgroundColor: Colors.white, + backgroundColor: 'white', flex: 1, flexDirection: 'row', alignItems: 'center', @@ -71,7 +70,7 @@ const styles = StyleSheet.create({ fontWeight: '700', fontSize: 16, lineHeight: 24, - color: Colors.black, + color: 'black', ...InterSemiBold, }, rightItem: { @@ -79,7 +78,7 @@ const styles = StyleSheet.create({ alignSelf: 'flex-end', }, rowData: { - color: Colors.gray[100], + color: 'goodGrey.400', textAlign: 'right', fontSize: 16, lineHeight: 24, @@ -88,10 +87,10 @@ const styles = StyleSheet.create({ rowBalance: { fontSize: 12, textAlign: 'right', - color: Colors.gray[200], + color: 'goodGrey.25', lineHeight: 18, ...InterRegular, }, -}); +} as const; export default RowItem; diff --git a/packages/app/src/components/StewardsList/StewardsListItem.tsx b/packages/app/src/components/StewardsList/StewardsListItem.tsx index 6c31f9a3..13eb243b 100644 --- a/packages/app/src/components/StewardsList/StewardsListItem.tsx +++ b/packages/app/src/components/StewardsList/StewardsListItem.tsx @@ -1,5 +1,4 @@ -import { Image, StyleSheet, Text, TouchableOpacity } from 'react-native'; -import { Colors } from '../../utils/colors'; +import { Text, Pressable, Image } from 'native-base'; import { InterRegular, InterSemiBold } from '../../utils/webFonts'; import { StewardCollective } from '../../models/models'; import { VerifiedIcon } from '../../assets'; @@ -26,17 +25,17 @@ export const StewardsListItem = (props: StewardListItemProps) => { const onClickSteward = () => navigate(`/profile/${steward.steward}`); return ( - + {userIdentifier} {isVerified && } {showActions && {steward.actions ?? 0} actions} - + ); }; -const styles = StyleSheet.create({ +const styles = { verifiedIcon: { height: 16, width: 16, @@ -44,7 +43,7 @@ const styles = StyleSheet.create({ row: { minHeight: 48, width: '100%', - backgroundColor: Colors.white, + backgroundColor: 'white', flex: 1, flexDirection: 'row', marginVertical: 8, @@ -54,13 +53,13 @@ const styles = StyleSheet.create({ fontSize: 16, ...InterSemiBold, width: '100%', - color: Colors.black, + color: 'black', }, totalActions: { fontSize: 14, ...InterRegular, textAlign: 'right', width: '100%', - color: Colors.gray[100], + color: 'goodGrey.400', }, -}); +} as const; diff --git a/packages/app/src/components/WalletDetails/EmptyProfile.tsx b/packages/app/src/components/WalletDetails/EmptyProfile.tsx index 60c8f40c..0b2b1a80 100644 --- a/packages/app/src/components/WalletDetails/EmptyProfile.tsx +++ b/packages/app/src/components/WalletDetails/EmptyProfile.tsx @@ -1,7 +1,6 @@ -import { StyleSheet, Text, View, Image } from 'react-native'; +import { Text, View, Image } from 'native-base'; import { InterSmall } from '../../utils/webFonts'; import RoundedButton from '../RoundedButton'; -import { Colors } from '../../utils/colors'; import useCrossNavigate from '../../routes/useCrossNavigate'; import { empty } from '../../assets'; @@ -9,13 +8,13 @@ function EmptyProfile() { const { navigate } = useCrossNavigate(); return ( - - It looks empty here. {'\n'} Donate to build your impact profile! - + + It looks empty here. {'\n'} Donate to build your impact profile! + empty navigate('/')} /> @@ -23,16 +22,16 @@ function EmptyProfile() { ); } -const styles = StyleSheet.create({ +const styles = { component: { gap: 32, - backgroundColor: Colors.white, + backgroundColor: 'white', }, text: { textAlign: 'center', width: '100', fontSize: 16, - color: Colors.gray[100], + color: 'goodGrey.400', ...InterSmall, }, @@ -41,6 +40,6 @@ const styles = StyleSheet.create({ width: 230, alignSelf: 'center', }, -}); +} as const; export default EmptyProfile; diff --git a/packages/app/src/components/WalletDetails/styles.ts b/packages/app/src/components/WalletDetails/styles.ts index 0b3232a0..0084beae 100644 --- a/packages/app/src/components/WalletDetails/styles.ts +++ b/packages/app/src/components/WalletDetails/styles.ts @@ -1,8 +1,6 @@ -import { StyleSheet } from 'react-native'; -import { Colors } from '../../utils/colors'; import { InterRegular, InterSemiBold } from '../../utils/webFonts'; -export const styles = StyleSheet.create({ +export const styles = { walletDetailsContainer: { flex: 1, flexDirection: 'column', @@ -13,13 +11,13 @@ export const styles = StyleSheet.create({ alignSelf: 'stretch', }, greenBar: { - backgroundColor: Colors.green[100], + backgroundColor: 'goodGreen.200', }, orangeBar: { - backgroundColor: Colors.orange[100], + backgroundColor: 'goodOrange.200', }, blueBar: { - backgroundColor: Colors.purple[300], + backgroundColor: 'goodPurple.250', }, row: { flexDirection: 'row', @@ -35,20 +33,20 @@ export const styles = StyleSheet.create({ rowBoldText: { fontSize: 18, ...InterSemiBold, - color: Colors.gray[100], + color: 'goodGrey.400', lineHeight: 27, }, rowText: { fontSize: 18, fontWeight: '400', fontFamily: 'Inter', - color: Colors.gray[100], + color: 'goodGrey.400', lineHeight: 27, }, formattedUsd: { fontSize: 12, lineHeight: 18, - color: Colors.gray[200], + color: 'goodGrey.25', ...InterRegular, }, -}); +} as const; diff --git a/packages/app/src/theme/theme.ts b/packages/app/src/theme/theme.ts index e402d4f7..ab87bbe3 100644 --- a/packages/app/src/theme/theme.ts +++ b/packages/app/src/theme/theme.ts @@ -20,14 +20,27 @@ export const nbTheme = extendTheme({ 400: '#5A5A5A', 500: '#1F2937', 600: '#D4D4D4', + 700: '#C7D4D8', }, goodPurple: { 100: '#E2EAFF', 200: '#D6E1FF', 300: '#CBDAFF', + 250: '#B8C8F2', 400: '#5B7AC6', 500: '#2B4483', }, + goodBlue: { + 200: '#3B7587', + }, + goodYellow: { + 100: '#FFDD28', + 200: '#B29706', + }, + goodBrown: { + 100: '#945C29', + 200: '#F2F2F2', + }, goodGreen: { 100: '#DBFDF4', 200: '#95EED8', @@ -39,6 +52,7 @@ export const nbTheme = extendTheme({ 100: '#FFE2C8', 200: '#FFC48E', 300: '#FFAD62', + 350: '#FFB674', 400: '#D86800', 500: '#AB5200', },