From 0bdf93607d92b984da170a4cf3379e653cf5d285 Mon Sep 17 00:00:00 2001 From: dev-rathore Date: Mon, 13 Jan 2025 19:57:37 +0530 Subject: [PATCH 1/3] bug fixes --- .../application-card.tsx | 87 ++++++++++-------- .../card/profile-modal/application-card.tsx | 90 +++++++++++-------- .../card-components/CollaborationHeader.tsx | 9 +- .../collaboration/CollaborationCard.tsx | 4 +- .../ApplicationsTabContent.tsx | 22 +++-- .../OverviewTabContent.tsx | 6 +- components/collaborations/index.tsx | 34 +------ components/contract-card/ContractHeader.tsx | 10 +-- .../contracts/ContractDetailContent.tsx | 10 +-- components/create-collaboration/index.tsx | 7 +- .../create-collaboration/screen-one.tsx | 9 +- .../create-collaboration/screen-three.tsx | 17 +++- .../create-collaboration/screen-two.tsx | 12 +-- components/proposals/Applications.tsx | 53 ++++++++++- hooks/request/use-applications.tsx | 12 ++- utils/date.ts | 56 ++++++++++++ 16 files changed, 276 insertions(+), 162 deletions(-) create mode 100644 utils/date.ts diff --git a/components/card/collaboration-details/application-card.tsx b/components/card/collaboration-details/application-card.tsx index 1d1ef2e2..e24ee4b9 100644 --- a/components/card/collaboration-details/application-card.tsx +++ b/components/card/collaboration-details/application-card.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Pressable } from 'react-native'; import Button from '../../ui/button'; import Carousel from '@/shared-uis/components/carousel/carousel'; import { useTheme } from '@react-navigation/native'; @@ -13,21 +14,21 @@ import { CardFooter } from '@/components/ui/card/secondary/card-footer'; import { processRawAttachment } from '@/utils/attachments'; import { Attachment } from '@/shared-libs/firestore/trendly-pro/constants/attachment'; import { InfluencerApplication } from '@/types/Collaboration'; -import { formatDistanceToNow } from "date-fns"; import { convertToKUnits } from '@/utils/conversion'; +import { formatTimeToNow } from '@/utils/date'; interface ApplicationCardProps { acceptApplication: () => void; + bottomSheetAction?: () => void; data: InfluencerApplication; - headerLeftAction?: () => void; - headerRightAction?: () => void; + profileModalAction?: () => void; } export const ApplicationCard: React.FC = ({ acceptApplication, + bottomSheetAction, data, - headerLeftAction, - headerRightAction, + profileModalAction, }) => { const theme = useTheme(); @@ -37,47 +38,55 @@ export const ApplicationCard: React.FC = ({ avatar={data.influencer.profileImage || ''} handle={data.influencer.socials?.[0]} isVerified={data.influencer.isVerified} - leftAction={headerLeftAction} + leftAction={profileModalAction} name={data.influencer.name} - rightAction={headerRightAction} - timestamp={formatDistanceToNow(data.application.timeStamp, { addSuffix: true })} + rightAction={bottomSheetAction} + timestamp={formatTimeToNow(data.application.timeStamp)} /> processRawAttachment(attachment))} theme={theme} /> - - + { + if (data.application.status === 'pending') { + acceptApplication(); + } }} - /> - Accept - - } - /> - - + > + + {data.application.status === 'pending' ? 'Accept' : 'Accepted'} + + } + /> + + + ); }; diff --git a/components/card/profile-modal/application-card.tsx b/components/card/profile-modal/application-card.tsx index 82cfedde..40b28149 100644 --- a/components/card/profile-modal/application-card.tsx +++ b/components/card/profile-modal/application-card.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Card } from '@/components/ui/card/tertiary'; import { CardHeader } from '@/components/ui/card/tertiary/card-header'; @@ -15,8 +15,8 @@ import { useTheme } from '@react-navigation/native'; interface ApplicationCardProps { data: Application; - onAccept: () => void; - onReject: () => void; + onAccept: () => Promise; + onReject: () => Promise; questions: { question: string; answer: string; @@ -30,6 +30,8 @@ export const ApplicationCard: React.FC = ({ questions, }) => { const theme = useTheme(); + const [acceptingApplication, setAcceptingApplication] = useState(false); + const [rejectingApplication, setRejectingApplication] = useState(false); return ( @@ -60,39 +62,55 @@ export const ApplicationCard: React.FC = ({ /> ) } - - - - - } - /> + { + data?.status === 'pending' && ( + + + + + } + /> + ) + } ); } diff --git a/components/collaboration-card/card-components/CollaborationHeader.tsx b/components/collaboration-card/card-components/CollaborationHeader.tsx index 99abf85f..3fdb91d4 100644 --- a/components/collaboration-card/card-components/CollaborationHeader.tsx +++ b/components/collaboration-card/card-components/CollaborationHeader.tsx @@ -1,13 +1,12 @@ import { Text, View } from "@/components/theme/Themed"; import { FC } from "react"; -import { formatDistanceToNow } from "date-fns"; -import { Avatar } from "react-native-paper"; -import { Image, Pressable } from "react-native"; +import { Pressable } from "react-native"; import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; import Colors from "@/constants/Colors"; import { faEllipsisH } from "@fortawesome/free-solid-svg-icons"; import { useTheme } from "@react-navigation/native"; import ImageComponent from "@/shared-uis/components/image-component"; +import { formatTimeToNow } from "@/utils/date"; interface CollaborationHeaderProps { collabName: string; @@ -96,9 +95,7 @@ const CollaborationHeader: FC = ({ > {timePosted ? ( - {formatDistanceToNow(timePosted, { - addSuffix: true, - })} + {formatTimeToNow(timePosted)} ) : null} { {/* Posted Date and Cost */} - Posted: {formatDistanceToNow(datePosted, { addSuffix: true })} + Posted: {formatTimeToNow(datePosted)} diff --git a/components/collaboration/collaboration-details/ApplicationsTabContent.tsx b/components/collaboration/collaboration-details/ApplicationsTabContent.tsx index 2ce69c13..50a199d9 100644 --- a/components/collaboration/collaboration-details/ApplicationsTabContent.tsx +++ b/components/collaboration/collaboration-details/ApplicationsTabContent.tsx @@ -118,17 +118,17 @@ const ApplicationsTabContent = (props: any) => { setSelectedInfluencerApplication(item); handleAcceptApplication(item); }} + bottomSheetAction={() => { + setSelectedInfluencerApplication(item); + setIsActionModalVisible(true); + }} data={item} - headerLeftAction={() => { + profileModalAction={() => { setSelectedInfluencerApplication(item); setTimeout(() => { bottomSheetModalRef.current?.present(); }, 500); }} - headerRightAction={() => { - setSelectedInfluencerApplication(item); - setIsActionModalVisible(true); - }} /> )} keyExtractor={(item, index) => item.application.id + index} @@ -198,11 +198,15 @@ const ApplicationsTabContent = (props: any) => { > { - handleRejectApplication(selectedInfluencerApplication as InfluencerApplication); + onReject={async () => { + await handleRejectApplication(selectedInfluencerApplication as InfluencerApplication).then(() => { + bottomSheetModalRef.current?.close(); + }); }} - onAccept={() => { - handleAcceptApplication(selectedInfluencerApplication as InfluencerApplication); + onAccept={async () => { + await handleAcceptApplication(selectedInfluencerApplication as InfluencerApplication).then(() => { + bottomSheetModalRef.current?.close(); + }); }} questions={selectedInfluencerApplication?.application.answersFromInfluencer.map((answer) => ({ question: collaborationQuestions[answer.question], diff --git a/components/collaboration/collaboration-details/OverviewTabContent.tsx b/components/collaboration/collaboration-details/OverviewTabContent.tsx index d57ede7d..1a30bf2e 100644 --- a/components/collaboration/collaboration-details/OverviewTabContent.tsx +++ b/components/collaboration/collaboration-details/OverviewTabContent.tsx @@ -18,7 +18,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; import Colors from "@/constants/Colors"; import Carousel from "@/shared-uis/components/carousel/carousel"; import { processRawAttachment } from "@/utils/attachments"; -import { formatDistanceToNow } from "date-fns"; import { truncateText } from "@/utils/text"; import ChipCard from "@/components/collaboration-card/card-components/ChipComponent"; import { @@ -33,6 +32,7 @@ import ManagerModal from "./modal/ManagerModal"; import { PromotionType } from "@/shared-libs/firestore/trendly-pro/constants/promotion-type"; import ViewCollaborationMap from "@/components/view-collaboration/ViewCollaborationMap"; import ImageComponent from "@/shared-uis/components/image-component"; +import { formatTimeToNow } from "@/utils/date"; interface CollaborationDetailsContentProps { collaboration: CollaborationDetail; @@ -147,9 +147,7 @@ const OverviewTabContent = (props: CollaborationDetailsContentProps) => { paddingRight: 8, }} > - {formatDistanceToNow(props.collaboration.timeStamp, { - addSuffix: true, - })} + {formatTimeToNow(props.collaboration.timeStamp)} ) : null} diff --git a/components/collaborations/index.tsx b/components/collaborations/index.tsx index 2318b103..15050027 100644 --- a/components/collaborations/index.tsx +++ b/components/collaborations/index.tsx @@ -3,10 +3,6 @@ import AppLayout from "@/layouts/app-layout"; import Applications from "@/components/proposals/Applications"; import Invitations from "@/components/proposals/Invitations"; import TopTabNavigation from "../ui/top-tab-navigation"; -import Button from "../ui/button"; -import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import { useRouter } from "expo-router"; const tabs = [ { @@ -22,45 +18,17 @@ const tabs = [ ]; const Collaborations = () => { - const router = useRouter(); - return ( - ); diff --git a/components/contract-card/ContractHeader.tsx b/components/contract-card/ContractHeader.tsx index fd2c2773..2201f608 100644 --- a/components/contract-card/ContractHeader.tsx +++ b/components/contract-card/ContractHeader.tsx @@ -1,14 +1,12 @@ import { Text, View } from "@/components/theme/Themed"; import { FC } from "react"; -import { formatDistanceToNow } from "date-fns"; -import { Avatar } from "react-native-paper"; -import { Image, Pressable } from "react-native"; +import { Pressable } from "react-native"; import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; import Colors from "@/constants/Colors"; import { faEllipsisH } from "@fortawesome/free-solid-svg-icons"; import { useTheme } from "@react-navigation/native"; -import { imageUrl } from "@/utils/url"; import ImageComponent from "@/shared-uis/components/image-component"; +import { formatTimeToNow } from "@/utils/date"; interface ContractHeaderProps { username: string; @@ -96,9 +94,7 @@ const ContractHeader: FC = ({ > {timePosted ? ( - {formatDistanceToNow(timePosted, { - addSuffix: true, - })} + {formatTimeToNow(timePosted)} ) : null} { paddingRight: 8, }} > - {formatDistanceToNow(props.collaborationDetail.timeStamp, { - addSuffix: true, - })} + {formatTimeToNow(props.collaborationDetail.timeStamp)} ) : null} diff --git a/components/create-collaboration/index.tsx b/components/create-collaboration/index.tsx index cf85b5a9..1d845068 100644 --- a/components/create-collaboration/index.tsx +++ b/components/create-collaboration/index.tsx @@ -217,7 +217,12 @@ const CreateCollaboration = () => { setScreen(4); setTimeout(() => { router.dismiss(1); - router.push("/collaborations"); + router.push({ + pathname: "/collaborations", + params: { + fetchNewCollaborations: "true", + }, + }); }, 3000); }).catch((error) => { console.error(error); diff --git a/components/create-collaboration/screen-one.tsx b/components/create-collaboration/screen-one.tsx index f2d50a5a..660695f3 100644 --- a/components/create-collaboration/screen-one.tsx +++ b/components/create-collaboration/screen-one.tsx @@ -16,7 +16,6 @@ import Button from "../ui/button"; import ContentWrapper from "@/shared-uis/components/content-wrapper"; import DragAndDropNative from "@/shared-uis/components/grid/native/DragAndDropNative"; import DragAndDropWeb from "@/shared-uis/components/grid/web/DragAndDropWeb"; -import stylesFn from "@/styles/create-collaboration/Screen.styles"; import TextInput from "../ui/text-input"; import ScreenLayout from "./screen-layout"; import { MultiSelectExtendable } from "@/shared-uis/components/multiselect-extendable"; @@ -129,6 +128,8 @@ const ScreenOne: React.FC = ({ { if (!isEdited) { setIsEdited(true); @@ -144,7 +145,11 @@ const ScreenOne: React.FC = ({ { setCollaboration({ ...collaboration, diff --git a/components/create-collaboration/screen-three.tsx b/components/create-collaboration/screen-three.tsx index 312b5abd..fb518c2a 100644 --- a/components/create-collaboration/screen-three.tsx +++ b/components/create-collaboration/screen-three.tsx @@ -49,7 +49,8 @@ const ScreenThree: React.FC = ({ name: "", link: "", }); - const [questions, setQuestions] = useState(collaboration.questionsToInfluencers || []); + const newQuestions = collaboration.questionsToInfluencers || [""]; + const [questions, setQuestions] = useState(newQuestions.length === 0 ? [""] : newQuestions); const handleAddExternalLink = () => { if (!externalLink.name || !externalLink.link) { @@ -100,7 +101,12 @@ const ScreenThree: React.FC = ({ }); setIsQuestionsModalVisible(false); - setQuestions(newQuestions); + + if (newQuestions.length === 0) { + setQuestions([...newQuestions, ""]); + } else { + setQuestions(newQuestions); + } } return ( @@ -321,6 +327,9 @@ const ScreenThree: React.FC = ({ /> { setExternalLink({ @@ -361,7 +370,7 @@ const ScreenThree: React.FC = ({ contentContainerStyle={styles.modalContainer} onDismiss={() => { setIsQuestionsModalVisible(false); - setQuestions(collaboration.questionsToInfluencers || []); + setQuestions(newQuestions.length === 0 ? [""] : newQuestions); }} visible={isQuestionsModalVisible} > @@ -423,7 +432,7 @@ const ScreenThree: React.FC = ({ marginRight: 8, }} /> - Add Questions + Add Question + + ) + } ); }; diff --git a/hooks/request/use-applications.tsx b/hooks/request/use-applications.tsx index 1841852b..a15498bf 100644 --- a/hooks/request/use-applications.tsx +++ b/hooks/request/use-applications.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { useRouter } from "expo-router"; -import { collection, getDocs, doc, updateDoc, getDoc } from "firebase/firestore"; +import { collection, getDocs, doc, updateDoc, getDoc, query, where } from "firebase/firestore"; import { useChatContext, useNotificationContext } from "@/contexts"; import Toaster from "@/shared-uis/components/toaster/Toaster"; @@ -42,7 +42,12 @@ const useApplications = ({ collaborationId, "applications" ); - const applicationFetch = await getDocs(applicationRef); + const applicationQuery = query( + applicationRef, + where("status", "in", ["pending", "accepted"]) + ); + const applicationFetch = await getDocs(applicationQuery); + const applications = applicationFetch.docs.map((doc) => { return { ...doc.data(), @@ -116,8 +121,8 @@ const useApplications = ({ router.navigate(`/channel/${channel.cid}`); }); + fetchApplications(); handleActionModalClose(); - Toaster.success("Application accepted successfully"); }); } catch (error) { @@ -143,6 +148,7 @@ const useApplications = ({ await updateDoc(applicationRef, { status: "rejected", }).then(() => { + fetchApplications(); handleActionModalClose(); Toaster.success("Application rejected successfully"); }); diff --git a/utils/date.ts b/utils/date.ts new file mode 100644 index 00000000..960fc30e --- /dev/null +++ b/utils/date.ts @@ -0,0 +1,56 @@ +import { DateArg, formatDistanceToNow } from "date-fns"; + +// Examples: +// For seconds: "sec ago" +// For minutes: "mins ago" +// For hours: "hrs ago" +// For days: "d ago" +// For weeks: "w ago" +// For months: "m ago" +// For years: "yrs ago" +export const formatTimeToNow = (date: DateArg): string => { + return formatDistanceToNow(date, { + addSuffix: true, + locale: { + formatDistance: (token, count, options) => { + if (token === "lessThanXSeconds") { + return `${count} sec ago`; + } + if (token === "xSeconds") { + return `${count} sec ago`; + } + if (token === "halfAMinute") { + return `${count} min ago`; + } + if (token === "lessThanXMinutes") { + return `${count} mins ago`; + } + if (token === "xMinutes") { + return `${count} mins ago`; + } + if (token === "aboutXHours") { + return `${count} hrs ago`; + } + if (token === "xHours") { + return `${count} hrs ago`; + } + if (token === "xDays") { + return `${count} d ago`; + } + if (token === "aboutXMonths") { + return `${count} m ago`; + } + if (token === "xMonths") { + return `${count} m ago`; + } + if (token === "aboutXYears") { + return `${count} yrs ago`; + } + if (token === "xYears") { + return `${count} yrs ago`; + } + return ""; + }, + }, + }); +}; From f1dd8f782394cf933229277a8a4f375bfcbfbc92 Mon Sep 17 00:00:00 2001 From: dev-rathore Date: Mon, 13 Jan 2025 20:26:43 +0530 Subject: [PATCH 2/3] bug fixes --- .../application-card.tsx | 3 +- .../collaboration-details/invitation-card.tsx | 2 + components/ui/card/secondary/card-actions.tsx | 8 +++- .../ui/card/secondary/card-description.tsx | 8 +++- components/ui/card/secondary/card-footer.tsx | 9 ++++- components/ui/card/secondary/card-header.tsx | 4 ++ utils/date.ts | 37 +++++++++---------- 7 files changed, 47 insertions(+), 24 deletions(-) diff --git a/components/card/collaboration-details/application-card.tsx b/components/card/collaboration-details/application-card.tsx index e24ee4b9..e564f9f7 100644 --- a/components/card/collaboration-details/application-card.tsx +++ b/components/card/collaboration-details/application-card.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Pressable } from 'react-native'; +import { Platform, Pressable } from 'react-native'; import Button from '../../ui/button'; import Carousel from '@/shared-uis/components/carousel/carousel'; import { useTheme } from '@react-navigation/native'; @@ -44,6 +44,7 @@ export const ApplicationCard: React.FC = ({ timestamp={formatTimeToNow(data.application.timeStamp)} /> processRawAttachment(attachment))} theme={theme} /> diff --git a/components/card/collaboration-details/invitation-card.tsx b/components/card/collaboration-details/invitation-card.tsx index a8f3f049..000a0190 100644 --- a/components/card/collaboration-details/invitation-card.tsx +++ b/components/card/collaboration-details/invitation-card.tsx @@ -12,6 +12,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { faCheck, faPlus } from '@fortawesome/free-solid-svg-icons'; import Colors from '@/constants/Colors'; import useInvitation from '@/hooks/use-invitation'; +import { Platform } from 'react-native'; interface InvitationCardProps { checkIfAlreadyInvited: (influencerId: string) => Promise; @@ -47,6 +48,7 @@ const InvitationCard: React.FC = ({ rightAction={headerRightAction} /> processRawAttachment(attachment)) || []} theme={theme} /> diff --git a/components/ui/card/secondary/card-actions.tsx b/components/ui/card/secondary/card-actions.tsx index 3bdf944c..09e82f78 100644 --- a/components/ui/card/secondary/card-actions.tsx +++ b/components/ui/card/secondary/card-actions.tsx @@ -4,7 +4,7 @@ import { Text, View } from '@/components/theme/Themed'; import Colors from '@/constants/Colors'; import { faChartLine, faFaceSmile, faPeopleRoof } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; -import { useTheme } from '@react-navigation/native'; +import { Theme, useTheme } from '@react-navigation/native'; import { convertToKUnits } from '@/utils/conversion'; type CardActionsProps = { @@ -21,6 +21,7 @@ export const CardActions = ({ action = null, }: CardActionsProps) => { const theme = useTheme(); + const styles = stylesFn(theme); return ( @@ -55,21 +56,24 @@ export const CardActions = ({ ); }; -const styles = StyleSheet.create({ +const stylesFn = (theme: Theme) => StyleSheet.create({ container: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 16, + backgroundColor: Colors(theme).transparent, }, metrics: { flexDirection: 'row', alignItems: 'center', + backgroundColor: Colors(theme).transparent, }, metric: { flexDirection: 'row', alignItems: 'center', marginRight: 16, + backgroundColor: Colors(theme).transparent, }, metricText: { marginLeft: 4, diff --git a/components/ui/card/secondary/card-description.tsx b/components/ui/card/secondary/card-description.tsx index 1b6e2e2c..fc7a168b 100644 --- a/components/ui/card/secondary/card-description.tsx +++ b/components/ui/card/secondary/card-description.tsx @@ -1,12 +1,17 @@ import React from 'react'; import { StyleSheet } from 'react-native'; import { Text, View } from '@/components/theme/Themed'; +import { Theme, useTheme } from '@react-navigation/native'; +import Colors from '@/constants/Colors'; type CardDescriptionProps = { text: string; }; export const CardDescription = ({ text }: CardDescriptionProps) => { + const theme = useTheme(); + const styles = stylesFn(theme); + return ( @@ -16,9 +21,10 @@ export const CardDescription = ({ text }: CardDescriptionProps) => { ); }; -const styles = StyleSheet.create({ +const stylesFn = (theme: Theme) => StyleSheet.create({ container: { paddingHorizontal: 16, + backgroundColor: Colors(theme).transparent, }, text: { fontSize: 14, diff --git a/components/ui/card/secondary/card-footer.tsx b/components/ui/card/secondary/card-footer.tsx index a955ab20..b49df3d6 100644 --- a/components/ui/card/secondary/card-footer.tsx +++ b/components/ui/card/secondary/card-footer.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { StyleSheet } from 'react-native'; import { Text, View } from '@/components/theme/Themed'; import { CURRENCY_SYMBOL } from '@/constants/Unit'; +import { Theme, useTheme } from '@react-navigation/native'; +import Colors from '@/constants/Colors'; type CardFooterProps = { quote: string; @@ -12,6 +14,9 @@ export const CardFooter = ({ quote, timeline, }: CardFooterProps) => { + const theme = useTheme(); + const styles = stylesFn(theme); + return ( @@ -22,14 +27,16 @@ export const CardFooter = ({ ); }; -const styles = StyleSheet.create({ +const stylesFn = (theme: Theme) => StyleSheet.create({ container: { paddingHorizontal: 16, + backgroundColor: Colors(theme).transparent, }, footer: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8, + backgroundColor: Colors(theme).transparent, }, footerText: { fontSize: 14, diff --git a/components/ui/card/secondary/card-header.tsx b/components/ui/card/secondary/card-header.tsx index 59eb9976..c406cc75 100644 --- a/components/ui/card/secondary/card-header.tsx +++ b/components/ui/card/secondary/card-header.tsx @@ -61,6 +61,7 @@ export const CardHeader = ({ gap: 12, flexDirection: 'row', alignItems: 'center', + backgroundColor: Colors(theme).transparent, }} > {timestamp && {timestamp}} @@ -84,6 +85,7 @@ const stylesFn = (theme: Theme) => StyleSheet.create({ alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 16, + backgroundColor: Colors(theme).transparent, }, leftContent: { flexDirection: 'row', @@ -108,11 +110,13 @@ const stylesFn = (theme: Theme) => StyleSheet.create({ }, userInfo: { marginLeft: 12, + backgroundColor: Colors(theme).transparent, }, nameContainer: { flexDirection: 'row', alignItems: 'center', gap: 2, + backgroundColor: Colors(theme).transparent, }, name: { fontSize: 16, diff --git a/utils/date.ts b/utils/date.ts index 960fc30e..e7526693 100644 --- a/utils/date.ts +++ b/utils/date.ts @@ -1,53 +1,52 @@ import { DateArg, formatDistanceToNow } from "date-fns"; // Examples: -// For seconds: "sec ago" -// For minutes: "mins ago" -// For hours: "hrs ago" -// For days: "d ago" -// For weeks: "w ago" -// For months: "m ago" -// For years: "yrs ago" +// For seconds: 1 second ago +// For minutes: 1m ago +// For hours: 1h ago +// For days: 1d ago +// For months: 1mon ago +// For years: 1y ago export const formatTimeToNow = (date: DateArg): string => { return formatDistanceToNow(date, { addSuffix: true, locale: { formatDistance: (token, count, options) => { if (token === "lessThanXSeconds") { - return `${count} sec ago`; + return `${count} second ago`; } if (token === "xSeconds") { - return `${count} sec ago`; + return `${count} seconds ago`; } if (token === "halfAMinute") { - return `${count} min ago`; + return `${count} seconds ago`; } if (token === "lessThanXMinutes") { - return `${count} mins ago`; + return `${count}m ago`; } if (token === "xMinutes") { - return `${count} mins ago`; + return `${count}m ago`; } if (token === "aboutXHours") { - return `${count} hrs ago`; + return `${count}h ago`; } if (token === "xHours") { - return `${count} hrs ago`; + return `${count}h ago`; } if (token === "xDays") { - return `${count} d ago`; + return `${count}d ago`; } if (token === "aboutXMonths") { - return `${count} m ago`; + return `${count}mon ago`; } if (token === "xMonths") { - return `${count} m ago`; + return `${count}mon ago`; } if (token === "aboutXYears") { - return `${count} yrs ago`; + return `${count}y ago`; } if (token === "xYears") { - return `${count} yrs ago`; + return `${count}y ago`; } return ""; }, From d45ec1bdd61454cf43e341429cc3deedd3a87ed7 Mon Sep 17 00:00:00 2001 From: dev-rathore Date: Mon, 13 Jan 2025 21:34:05 +0530 Subject: [PATCH 3/3] message screen fix --- app/(main)/(screens)/(menu)/brand-profile.tsx | 46 ++++++++++++++----- .../(onboarding)/onboarding-your-brand.tsx | 17 ++++--- components/channel/channel-list.tsx | 22 ++------- components/channel/channel.tsx | 1 - components/channel/empty-message-state.tsx | 27 +++++++++++ .../create-collaboration/screen-layout.tsx | 7 +-- components/profile/index.tsx | 5 +- 7 files changed, 82 insertions(+), 43 deletions(-) create mode 100644 components/channel/empty-message-state.tsx diff --git a/app/(main)/(screens)/(menu)/brand-profile.tsx b/app/(main)/(screens)/(menu)/brand-profile.tsx index 865dd162..fd759a15 100644 --- a/app/(main)/(screens)/(menu)/brand-profile.tsx +++ b/app/(main)/(screens)/(menu)/brand-profile.tsx @@ -1,25 +1,29 @@ import React, { useRef, useState } from "react"; -import { Pressable } from "react-native"; +import { ActivityIndicator, Pressable } from "react-native"; import Toast from "react-native-toast-message"; import { Brand } from "@/types/Brand"; import { Text } from "@/components/theme/Themed"; -import { useAuthContext, useFirebaseStorageContext } from "@/contexts"; +import { useAuthContext, useAWSContext } from "@/contexts"; import { useBrandContext } from "@/contexts/brand-context.provider"; import AppLayout from "@/layouts/app-layout"; import BrandProfile from "@/components/brand-profile"; import ScreenHeader from "@/components/ui/screen-header"; import Toaster from "@/shared-uis/components/toaster/Toaster"; +import Colors from "@/constants/Colors"; +import { useTheme } from "@react-navigation/native"; const BrandProfileScreen = () => { + const [isSaving, setIsSaving] = useState(false); + const { updateBrand, selectedBrand, setSelectedBrand, } = useBrandContext(); - const { - uploadImageBytes, - } = useFirebaseStorageContext(); + const { uploadFileUri } = useAWSContext(); + + const theme = useTheme(); const { manager: user, @@ -38,12 +42,16 @@ const BrandProfileScreen = () => { Toaster.error('Brand name is required'); } + setIsSaving(true); let imageUrl = ""; - if (brandData.image !== brandImage.current) { - const blob = await fetch( - brandData.image as string, - ).then((res) => res.blob()); - imageUrl = await uploadImageBytes(blob, `brands/${brandData.name}-${Date.now()}`); + if (brandData.image && brandData.image !== brandImage.current) { + const uploadedImage = await uploadFileUri({ + id: brandData.image, + localUri: brandData.image, + uri: brandData.image, + type: "image", + }); + imageUrl = uploadedImage.imageUrl; } await updateBrand( @@ -57,6 +65,8 @@ const BrandProfileScreen = () => { setSelectedBrand(brandData as Brand); }).catch((error) => { Toaster.error('Error saving preferences'); + }).finally(() => { + setIsSaving(false); }); } @@ -68,8 +78,22 @@ const BrandProfileScreen = () => { rightActionButton={ + { + isSaving && ( + + ) + } Save } diff --git a/app/(main)/(screens)/(onboarding)/onboarding-your-brand.tsx b/app/(main)/(screens)/(onboarding)/onboarding-your-brand.tsx index ab4ceb8a..8b4355c5 100644 --- a/app/(main)/(screens)/(onboarding)/onboarding-your-brand.tsx +++ b/app/(main)/(screens)/(onboarding)/onboarding-your-brand.tsx @@ -8,7 +8,7 @@ import { addDoc, collection, doc, setDoc } from "firebase/firestore"; import { Brand } from "@/types/Brand"; import { FirestoreDB } from "@/utils/firestore"; import { useBrandContext } from "@/contexts/brand-context.provider"; -import { useAuthContext, useFirebaseStorageContext } from "@/contexts"; +import { useAuthContext, useAWSContext } from "@/contexts"; import AppLayout from "@/layouts/app-layout"; import BrandProfile from "@/components/brand-profile"; import fnStyles from "@/styles/onboarding/brand.styles"; @@ -37,10 +37,11 @@ const OnboardingScreen = () => { const theme = useTheme(); const styles = fnStyles(theme); const { firstBrand } = useLocalSearchParams(); - const { uploadImageBytes } = useFirebaseStorageContext(); + const { uploadFileUri } = useAWSContext(); const { setSelectedBrand } = useBrandContext(); const { manager: user } = useAuthContext(); + const handleCreateBrand = async () => { setIsSubmitting(true); if (!user) { @@ -59,11 +60,13 @@ const OnboardingScreen = () => { let imageUrl = ""; if (brandData.image) { - const blob = await fetch(brandData.image).then((res) => res.blob()); - imageUrl = await uploadImageBytes( - blob, - `brands/${brandData.name}-${Date.now()}` - ); + const uploadedImage = await uploadFileUri({ + id: brandData.image, + localUri: brandData.image, + uri: brandData.image, + type: "image", + }); + imageUrl = uploadedImage.imageUrl; } if (user) { diff --git a/components/channel/channel-list.tsx b/components/channel/channel-list.tsx index 2d40b9a4..1cf7a54a 100644 --- a/components/channel/channel-list.tsx +++ b/components/channel/channel-list.tsx @@ -13,7 +13,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; import { faMagnifyingGlass, faPlus } from "@fortawesome/free-solid-svg-icons"; import stylesFn from "@/styles/searchbar/Searchbar.styles"; import { Pressable } from "react-native"; -import EmptyState from "../ui/empty-state"; +import EmptyMessageState from "./empty-message-state"; const ChannelListNative = () => { const [modalVisible, setModalVisible] = useState(false); @@ -79,23 +79,9 @@ const ChannelListNative = () => { /> ( - - router.push("/collaborations")} - actionLabel="Explore Collaborations" - image={require("@/assets/images/illustration3.png")} - subtitle="Start applying to collaborations to interact with your dream brands." - title="No Messages" - /> - - )} + EmptyStateIndicator={EmptyMessageState} + LoadingErrorIndicator={EmptyMessageState} + LoadingIndicator={EmptyMessageState} channelRenderFilterFn={customChannelFilterFunction} filters={{ members: { $in: [user?.id as string] }, diff --git a/components/channel/channel.tsx b/components/channel/channel.tsx index d7a50425..bd3abcd7 100644 --- a/components/channel/channel.tsx +++ b/components/channel/channel.tsx @@ -92,7 +92,6 @@ const ChannelNative = () => { { router.push(`/contract-details/${contract.streamChannelId}`); diff --git a/components/channel/empty-message-state.tsx b/components/channel/empty-message-state.tsx new file mode 100644 index 00000000..d73217d0 --- /dev/null +++ b/components/channel/empty-message-state.tsx @@ -0,0 +1,27 @@ +import { useRouter } from "expo-router"; +import { View } from "../theme/Themed"; +import EmptyState from "../ui/empty-state"; + +const EmptyMessageState: React.FC = () => { + const router = useRouter(); + + return ( + + router.push("/collaborations")} + actionLabel="Explore Collaborations" + image={require("@/assets/images/illustration3.png")} + subtitle="Start applying to collaborations to interact with your dream brands." + title="No Messages" + /> + + ); +}; + +export default EmptyMessageState; diff --git a/components/create-collaboration/screen-layout.tsx b/components/create-collaboration/screen-layout.tsx index 7a23df1e..162f70c8 100644 --- a/components/create-collaboration/screen-layout.tsx +++ b/components/create-collaboration/screen-layout.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { Platform, Pressable, ScrollView } from "react-native"; +import { KeyboardAvoidingView, Platform, Pressable, ScrollView } from "react-native"; import { View } from "../theme/Themed"; import { useTheme } from "@react-navigation/native"; import { faClose } from "@fortawesome/free-solid-svg-icons"; @@ -35,7 +35,8 @@ const ScreenLayout: React.FC = ({ const [isModalVisible, setIsModalVisible] = useState(false); return ( - = ({ cancelText="Discard" description="Are you sure you want to discard the changes? You can save as draft instead" /> - + ); }; diff --git a/components/profile/index.tsx b/components/profile/index.tsx index 6c060c87..30839761 100644 --- a/components/profile/index.tsx +++ b/components/profile/index.tsx @@ -8,11 +8,10 @@ import { ScrollView, ActivityIndicator, } from "react-native"; -import { TextInput, Button, Avatar } from "react-native-paper"; +import { TextInput, Button } from "react-native-paper"; import { doc, getDoc, updateDoc } from "firebase/firestore"; import Colors from "@/constants/Colors"; -import { PLACEHOLDER_PERSON_IMAGE } from "@/constants/Placeholder"; -import { useAuthContext, useFirebaseStorageContext } from "@/contexts"; +import { useAuthContext } from "@/contexts"; import { useTheme } from "@react-navigation/native"; import { faPen } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";