diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index b647118..e5befc0 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -81,53 +81,53 @@ jobs: run: docker push ghcr.io/$GITHUB_REPOSITORY --all-tags - # deploy_backend: - # runs-on: ubuntu-22.04 - # defaults: - # run: - # shell: bash - # if: github.ref_name == 'main' || github.ref_name == 'dev' - # env: - # GITHUB_USERNAME: ${{ github.actor }} - # GITHUB_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - # PORT: ${{ vars.PORT }} - # REACT_APP_CUSTOMER_PORTAL_LINK: ${{ vars.REACT_APP_CUSTOMER_PORTAL_LINK }} - # GOOGLE_CLIENT_ID: ${{ github.ref_name == 'main' && secrets.PROD_GOOGLE_CLIENT_ID || secrets.STAGING_GOOGLE_CLIENT_ID }} - # GOOGLE_CLIENT_SECRET: ${{ github.ref_name == 'main' && secrets.PROD_GOOGLE_CLIENT_SECRET || secrets.STAGING_GOOGLE_CLIENT_SECRET }} - # ADMIN_EMAILS: ${{ vars.ADMIN_EMAILS }} - - # WASP_SERVER_URL: ${{ github.ref_name == 'main' && vars.PROD_WASP_SERVER_URL || vars.STAGING_WASP_SERVER_URL }} - # ADS_SERVER_URL: ${{ github.ref_name == 'main' && vars.PROD_ADS_SERVER_URL || vars.STAGING_ADS_SERVER_URL }} - # BACKEND_DOMAIN: ${{ github.ref_name == 'main' && vars.PROD_BACKEND_DOMAIN || vars.STAGING_BACKEND_DOMAIN }} - # WASP_WEB_CLIENT_URL: ${{ github.ref_name == 'main' && vars.PROD_WASP_WEB_CLIENT_URL || vars.STAGING_WASP_WEB_CLIENT_URL }} - # DATABASE_URL: ${{ github.ref_name == 'main' && secrets.PROD_DATABASE_URL || secrets.STAGING_DATABASE_URL }} - # REACT_APP_API_URL: ${{ github.ref_name == 'main' && vars.PROD_REACT_APP_API_URL || vars.STAGING_REACT_APP_API_URL }} - # JWT_SECRET: ${{ github.ref_name == 'main' && secrets.PROD_JWT_SECRET || secrets.STAGING_JWT_SECRET }} - # PRO_SUBSCRIPTION_PRICE_ID: ${{ github.ref_name == 'main' && secrets.PROD_PRO_SUBSCRIPTION_PRICE_ID || secrets.STAGING_PRO_SUBSCRIPTION_PRICE_ID }} - # STRIPE_KEY: ${{ github.ref_name == 'main' && secrets.PROD_STRIPE_KEY || secrets.STAGING_STRIPE_KEY }} - # STRIPE_WEBHOOK_SECRET: ${{ github.ref_name == 'main' && secrets.PROD_STRIPE_WEBHOOK_SECRET || secrets.STAGING_STRIPE_WEBHOOK_SECRET }} - # SSH_KEY: ${{ github.ref_name == 'main' && secrets.PROD_SSH_KEY || secrets.STAGING_SSH_KEY }} - # steps: - # - uses: actions/checkout@v3 - # # This is to fix GIT not liking owner of the checkout dir - https://github.com/actions/runner/issues/2033#issuecomment-1204205989 - # - run: chown -R $(id -u):$(id -g) $PWD - - # - run: if [[ $GITHUB_REF_NAME == "main" ]]; then echo "TAG=latest" >> $GITHUB_ENV ; else echo "TAG=dev" >> $GITHUB_ENV ; fi; - - # - run: echo "PATH=$PATH:/github/home/.local/bin" >> $GITHUB_ENV - # - run: 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client git -y )' - # - run: eval $(ssh-agent -s) - # - run: mkdir -p ~/.ssh - # - run: chmod 700 ~/.ssh - # - run: ssh-keyscan "$BACKEND_DOMAIN" >> ~/.ssh/known_hosts - # - run: chmod 644 ~/.ssh/known_hosts - # - run: echo "$SSH_KEY" | base64 --decode > key.pem - # - run: chmod 600 key.pem - - # - run: ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker images" - # - run: bash scripts/deploy_backend.sh - - # - run: rm key.pem + deploy_backend: + runs-on: ubuntu-22.04 + defaults: + run: + shell: bash + if: github.ref_name == 'main' || github.ref_name == 'dev' + env: + GITHUB_USERNAME: ${{ github.actor }} + GITHUB_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + PORT: ${{ vars.PORT }} + REACT_APP_CUSTOMER_PORTAL_LINK: ${{ vars.REACT_APP_CUSTOMER_PORTAL_LINK }} + GOOGLE_CLIENT_ID: ${{ github.ref_name == 'main' && secrets.PROD_GOOGLE_CLIENT_ID || secrets.STAGING_GOOGLE_CLIENT_ID }} + GOOGLE_CLIENT_SECRET: ${{ github.ref_name == 'main' && secrets.PROD_GOOGLE_CLIENT_SECRET || secrets.STAGING_GOOGLE_CLIENT_SECRET }} + ADMIN_EMAILS: ${{ vars.ADMIN_EMAILS }} + + WASP_SERVER_URL: ${{ github.ref_name == 'main' && vars.PROD_WASP_SERVER_URL || vars.STAGING_WASP_SERVER_URL }} + ADS_SERVER_URL: ${{ github.ref_name == 'main' && vars.PROD_ADS_SERVER_URL || vars.STAGING_ADS_SERVER_URL }} + BACKEND_DOMAIN: ${{ github.ref_name == 'main' && vars.PROD_BACKEND_DOMAIN || vars.STAGING_BACKEND_DOMAIN }} + WASP_WEB_CLIENT_URL: ${{ github.ref_name == 'main' && vars.PROD_WASP_WEB_CLIENT_URL || vars.STAGING_WASP_WEB_CLIENT_URL }} + DATABASE_URL: ${{ github.ref_name == 'main' && secrets.PROD_DATABASE_URL || secrets.STAGING_DATABASE_URL }} + REACT_APP_API_URL: ${{ github.ref_name == 'main' && vars.PROD_REACT_APP_API_URL || vars.STAGING_REACT_APP_API_URL }} + JWT_SECRET: ${{ github.ref_name == 'main' && secrets.PROD_JWT_SECRET || secrets.STAGING_JWT_SECRET }} + PRO_SUBSCRIPTION_PRICE_ID: ${{ github.ref_name == 'main' && secrets.PROD_PRO_SUBSCRIPTION_PRICE_ID || secrets.STAGING_PRO_SUBSCRIPTION_PRICE_ID }} + STRIPE_KEY: ${{ github.ref_name == 'main' && secrets.PROD_STRIPE_KEY || secrets.STAGING_STRIPE_KEY }} + STRIPE_WEBHOOK_SECRET: ${{ github.ref_name == 'main' && secrets.PROD_STRIPE_WEBHOOK_SECRET || secrets.STAGING_STRIPE_WEBHOOK_SECRET }} + SSH_KEY: ${{ github.ref_name == 'main' && secrets.PROD_SSH_KEY || secrets.STAGING_SSH_KEY }} + steps: + - uses: actions/checkout@v3 + # This is to fix GIT not liking owner of the checkout dir - https://github.com/actions/runner/issues/2033#issuecomment-1204205989 + - run: chown -R $(id -u):$(id -g) $PWD + + - run: if [[ $GITHUB_REF_NAME == "main" ]]; then echo "TAG=latest" >> $GITHUB_ENV ; else echo "TAG=dev" >> $GITHUB_ENV ; fi; + + - run: echo "PATH=$PATH:/github/home/.local/bin" >> $GITHUB_ENV + - run: 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client git -y )' + - run: eval $(ssh-agent -s) + - run: mkdir -p ~/.ssh + - run: chmod 700 ~/.ssh + - run: ssh-keyscan "$BACKEND_DOMAIN" >> ~/.ssh/known_hosts + - run: chmod 644 ~/.ssh/known_hosts + - run: echo "$SSH_KEY" | base64 --decode > key.pem + - run: chmod 600 key.pem + + - run: ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker images" + - run: bash scripts/deploy_backend.sh + + - run: rm key.pem deploy_frontend: runs-on: ubuntu-22.04 @@ -135,13 +135,10 @@ jobs: contents: write if: github.ref_name == 'main' || github.ref_name == 'dev' env: - # STAGING_BACKEND_DOMAIN: ${{ vars.STAGING_BACKEND_DOMAIN }} - # STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }} - # REACT_APP_CUSTOMER_PORTAL_LINK: ${{ vars.REACT_APP_CUSTOMER_PORTAL_LINK }} - # REACT_APP_API_URL: ${{ github.ref_name == 'main' && vars.PROD_REACT_APP_API_URL || vars.STAGING_REACT_APP_API_URL }} - - REACT_APP_CUSTOMER_PORTAL_LINK: "" - REACT_APP_API_URL: "" + STAGING_BACKEND_DOMAIN: ${{ vars.STAGING_BACKEND_DOMAIN }} + STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }} + REACT_APP_CUSTOMER_PORTAL_LINK: ${{ vars.REACT_APP_CUSTOMER_PORTAL_LINK }} + REACT_APP_API_URL: ${{ github.ref_name == 'main' && vars.PROD_REACT_APP_API_URL || vars.STAGING_REACT_APP_API_URL }} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -171,18 +168,18 @@ jobs: with: folder: app/.wasp/build/web-app/build - # - name: Deploy UI to staging - # if: github.ref_name == 'dev' - # run: | - # apt-get update -y && apt-get install openssh-client git -y - # eval $(ssh-agent -s) - # mkdir -p ~/.ssh - # chmod 700 ~/.ssh - # ssh-keyscan "$STAGING_BACKEND_DOMAIN" >> ~/.ssh/known_hosts - # chmod 644 ~/.ssh/known_hosts - # echo "$STAGING_SSH_KEY" | base64 --decode > key.pem - # chmod 600 key.pem - # ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$STAGING_BACKEND_DOMAIN" "ls -lah /var/www/html/UI" - # scp -i key.pem -r app/.wasp/build/web-app/build azureuser@"$STAGING_BACKEND_DOMAIN":/var/www/html/UI - # ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$STAGING_BACKEND_DOMAIN" "ls -lah /var/www/html/UI" - # rm key.pem + - name: Deploy UI to staging + if: github.ref_name == 'dev' + run: | + apt-get update -y && apt-get install openssh-client git -y + eval $(ssh-agent -s) + mkdir -p ~/.ssh + chmod 700 ~/.ssh + ssh-keyscan "$STAGING_BACKEND_DOMAIN" >> ~/.ssh/known_hosts + chmod 644 ~/.ssh/known_hosts + echo "$STAGING_SSH_KEY" | base64 --decode > key.pem + chmod 600 key.pem + ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$STAGING_BACKEND_DOMAIN" "ls -lah /var/www/html/UI" + scp -i key.pem -r app/.wasp/build/web-app/build azureuser@"$STAGING_BACKEND_DOMAIN":/var/www/html/UI + ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$STAGING_BACKEND_DOMAIN" "ls -lah /var/www/html/UI" + rm key.pem diff --git a/app/main.wasp b/app/main.wasp index 69e25d1..1c55f03 100644 --- a/app/main.wasp +++ b/app/main.wasp @@ -31,7 +31,7 @@ app OpenSaaS { }, }, onAuthFailedRedirectTo: "/login", - onAuthSucceededRedirectTo: "/", + onAuthSucceededRedirectTo: "/chat", }, db: { system: PostgreSQL, @@ -67,6 +67,9 @@ entity User {=psl createdAt DateTime @default(now()) lastActiveTimestamp DateTime @default(now()) isAdmin Boolean @default(false) + hasAcceptedTos Boolean @default(false) + hasSubscribedToMarketingEmails Boolean @default(false) + isSignUpComplete Boolean @default(false) stripeId String? checkoutSessionId String? hasPaid Boolean @default(false) @@ -148,6 +151,15 @@ page CheckoutPage { component: import Checkout from "@src/client/app/CheckoutPage" } +route TocPageRoute { path: "/toc", to: TocPage } +page TocPage { + component: import TocPage from "@src/client/app/TocPage", +} +route PrivacyRoute { path: "/privacy", to: PrivacyPage } +page PrivacyPage { + component: import PrivacyPage from "@src/client/app/PrivacyPage", +} + route AdminRoute { path: "/admin", to: DashboardPage } page DashboardPage { authRequired: true, diff --git a/app/migrations/20240412085104_add_fields_to_user_entity_to_trach_signup_complete_status/migration.sql b/app/migrations/20240412085104_add_fields_to_user_entity_to_trach_signup_complete_status/migration.sql new file mode 100644 index 0000000..29da96f --- /dev/null +++ b/app/migrations/20240412085104_add_fields_to_user_entity_to_trach_signup_complete_status/migration.sql @@ -0,0 +1,4 @@ +-- AlterTable +ALTER TABLE "User" ADD COLUMN "hasAcceptedTos" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "hasSubscribedToMarketingEmails" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "isSignUpComplete" BOOLEAN NOT NULL DEFAULT false; diff --git a/app/src/client/App.tsx b/app/src/client/App.tsx index 7246ffa..546e916 100644 --- a/app/src/client/App.tsx +++ b/app/src/client/App.tsx @@ -1,4 +1,4 @@ -import { useMemo, useEffect, ReactNode } from 'react'; +import { useMemo, useEffect, ReactNode, useState } from 'react'; import { useLocation } from 'react-router-dom'; import './Main.css'; @@ -10,6 +10,7 @@ import AppNavBar from './components/AppNavBar'; import Footer from './components/Footer'; import ServerNotRechableComponent from './components/ServerNotRechableComponent'; import LoadingComponent from './components/LoadingComponent'; +import TosAndMarketingEmailsModal from './components/TosAndMarketingEmailsModal'; const addServerErrorClass = () => { if (!document.body.classList.contains('server-error')) { @@ -29,6 +30,7 @@ const removeServerErrorClass = () => { */ export default function App({ children }: { children: ReactNode }) { const location = useLocation(); + const [showTosAndMarketingEmailsModal, setShowTosAndMarketingEmailsModal] = useState(false); const { data: user, isError, isLoading } = useAuth(); const shouldDisplayAppNavBar = useMemo(() => { @@ -39,12 +41,48 @@ export default function App({ children }: { children: ReactNode }) { return location.pathname.startsWith('/admin'); }, [location]); + const isCheckoutPage = useMemo(() => { + return location.pathname.startsWith('/checkout'); + }, [location]); + + const isAccountPage = useMemo(() => { + return location.pathname.startsWith('/account'); + }, [location]); + + const isChatPage = useMemo(() => { + return location.pathname.startsWith('/chat'); + }, [location]); + useEffect(() => { if (user) { - const lastSeenAt = new Date(user.lastActiveTimestamp); - const today = new Date(); - if (today.getTime() - lastSeenAt.getTime() > 5 * 60 * 1000) { - updateCurrentUser({ lastActiveTimestamp: today }); + console.log('user', user); + if (!user.isSignUpComplete) { + if (user.hasAcceptedTos) { + updateCurrentUser({ + isSignUpComplete: true, + }); + setShowTosAndMarketingEmailsModal(false); + } else { + const hasAcceptedTos = localStorage.getItem('hasAcceptedTos') === 'true'; + const hasSubscribedToMarketingEmails = localStorage.getItem('hasSubscribedToMarketingEmails') === 'true'; + if (!hasAcceptedTos) { + setShowTosAndMarketingEmailsModal(true); + } else { + updateCurrentUser({ + isSignUpComplete: true, + hasAcceptedTos: hasAcceptedTos, + hasSubscribedToMarketingEmails: hasSubscribedToMarketingEmails, + }); + setShowTosAndMarketingEmailsModal(false); + } + } + } else { + setShowTosAndMarketingEmailsModal(false); + const lastSeenAt = new Date(user.lastActiveTimestamp); + const today = new Date(); + if (today.getTime() - lastSeenAt.getTime() > 5 * 60 * 1000) { + updateCurrentUser({ lastActiveTimestamp: today }); + } } } }, [user]); @@ -63,13 +101,51 @@ export default function App({ children }: { children: ReactNode }) { <>
+ © 2024 airt. All rights reserved. +
+Last updated January 29, 2024
+ ++ Airt technologies, Inc. ("we", "us", or "our") is committed to protecting the privacy of our users. This + Privacy Policy explains how we collect, use, and disclose information through our SaaS tool,{' '} + Capt’n.ai (the "Service"). +
++ At Capt’n.ai, we value your privacy and are committed to ensuring the highest level of confidentiality and + security for your information. Here's what you need to know about the information we collect when you use + our Service: +
+We use the information we collect to:
++ User authenticates with the 3rd party provider such as Google account. Upon authentication, user allows + the application: +
++ Email address is stored in the database of the application while the other credentials of authenticated + users are encrypted and stored within the infrastructure of Google. This can be used to restrict or fully + block the service for a particular user in case of the breach of the terms of use. User's email + address can be deleted upon the request. +
++ To remove access of the application to your account, you can do it directly in your Google account by + following this link:{' '} + + https://myaccount.google.com/permissions + +
++ Capt’n.ai's use and transfer of information received from Google APIs adhere to{' '} + + Google API Services User Data Policy + + , including the Limited Use requirements. We recommend reviewing Google API Services User Data Policy to + better understand their practices. +
++ When you choose to connect various Google services to Capt’n.ai, we require specific permissions to fetch + and display data for your interactive queries. Below are the permissions required for each Google service: +
+You may choose to connect one, multiple, or none of these services as per your preference.
++ Our chatbot service utilizes advanced AI technology by employing privately deployed OpenAI models on + Microsoft Azure. This approach allows us to generate contextually relevant and accurate responses based on + your interactions and queries, ensuring a high-quality user experience. +
++ Your chat interactions are processed using our privately deployed OpenAI models on Microsoft Azure. This + ensures that your data, including chat history, user metrics, and dimensions from integrated services like + Google Analytics, Google Ads, and Facebook Ads, is not shared with OpenAI directly. +
+Here's a breakdown of the specific data shared from each source:
++ Google Analytics: Your Google Analytics data includes website traffic information, user behavior, + and engagement metrics from your connected websites. Metrics like page views, session duration, bounce + rate, and user demographics. By incorporating these insights, the chatbot can tailor its responses to + align with the user's website-related inquiries. +
++ Google Ads: Data from your Google Ads campaigns offers insights into your advertising efforts, ad + performance, and user interactions with your advertisements. Key metrics such as ad clicks, impressions, + click-through rates (CTR), and conversion rates are integrated into the chatbot's learning process. This + integration enables the chatbot to provide more informed and relevant responses regarding your advertising + strategies. +
++ Google Search Console: Information gathered from Google Search Console sheds light on your + website's visibility in Google search results. Details about search queries, click-through rates (CTR), + and average position help the chatbot understand user intent and prevalent search trends. By leveraging + this data, the chatbot can offer insights and answers that align with current search behaviors. +
++ Chat Interactions: This refers to the text-based interactions you have with the chatbot within the + Capt’n.ai platform. The content of these conversations, including your questions and responses. This data + aids in refining the AI's ability to comprehend inputs and generate contextually accurate responses. +
++ All of the data sources mentioned above are crucial for enhancing the chatbot's ability to provide + accurate and contextually relevant responses. When chatting directly on our website, certain data points + from your interactions and connected platforms are processed using our privately deployed OpenAI models on + Microsoft Azure. We ensure that only relevant and necessary data are shared to maintain the effectiveness + of the chatbot's functionality. +
++ While we do not directly store raw data from third-party sources such as Google Ads, Google Analytics, or + Facebook Ads, it's crucial to understand that your chat history may contain references to or summaries of + data from these services. Retaining this chat history is not just for record-keeping; it's a fundamental + component for the seamless functionality of our chatbot service. This chat data is securely stored in + Azure Database service, a cloud-based database, in compliance with Azure privacy policy ( + + https://learn.microsoft.com/en-us/azure/compliance/ + + ). Your chat history is retained indefinitely, but you have the option to delete it at any time through + the settings in our application. +
++ During your registration with Capt’n.ai, we require your explicit consent regarding our privacy practices. + As part of the sign-up process, you will encounter a checkbox indicating that you have read and agree to + our Terms and Conditions and Privacy Policy. By checking this box, you acknowledge your understanding and + agreement to how we handle your data as detailed in these documents. Only upon agreeing to these terms + will the chatbot service proceed with using your data. You have the option to withdraw your consent at any + point, read more below. +
++ If you choose to withdraw your consent and opt-out of data sharing with third-party tools, you will no + longer be able to use the Capt’n.ai service. The nature of our tool requires data sharing for its basic + functionality. Therefore, opting out effectively means discontinuing use of the service. +
++ By using our chatbot service, you explicitly consent to your chat data being processed as described above. + We ensure that your data is handled securely and in accordance with this privacy policy, as well as Azure + privacy policy. +
++ If you do not agree with this policy, please refrain from signing up and using Capt’n.ai. +
++ Google Analytics is used across captn.ai domain in order to collect information about the users' + interactions with the site as well as to identify returning visits, location, device data and engagement + signals. Collected data helps to understand the relevancy and general usage of the tool hence, to provide + better experience and solutions towards the needs of the users, fix errors and bugs. No data is shared + with the 3rd party organizations or individuals. +
+We may share your information with third parties in the following circumstances:
++ You can access and update your account information through the Service. You can also unsubscribe from our + promotional emails by following the instructions in the email. +
++ We retain the information we collect for as long as necessary to provide the Service and fulfill the + purposes described in this Privacy Policy. When we no longer need the information, we will securely delete + it or de-identify it. Your chat history is retained indefinitely, but you have the option to delete it at + any time through the settings in our application. +
++ We take reasonable measures to protect your information from unauthorized access, use, disclosure, and + destruction. However, no method of transmission over the internet or method of electronic storage is + completely secure. +
++ We may update this Privacy Policy from time to time. If we make any material changes, we will notify you + by email or by posting a notice on our website prior to the change becoming effective. +
++ In order to receive further information regarding use of the Site, please contact us at:{' '} + + support@captn.ai + + . +
+Last updated January 29, 2024
+ ++ These terms and conditions ("Terms") govern your access to and use of Capt’n.ai, a Software-as-a-Service + tool ("Service") provided by airt technologies, Inc. ("we" or "us"). By accessing or using the Service, + you agree to be bound by these Terms. If you do not agree to these Terms, you may not access or use the + Service. +
++ Subject to these Terms, we grant you a limited, non-exclusive, non-transferable, revocable license to use + the Service for your internal business purposes during the term of these Terms. +
++ You may not use the Service in any way that could damage, disable, overburden, or impair the Service or + interfere with any other party's use and enjoyment of the Service. You may not attempt to gain + unauthorized access to the Service or any part of it, other accounts, computer systems, or networks + connected to the Service, through hacking, password mining, or any other means. +
++ You are solely responsible for all data, information, and content uploaded, stored, or processed using the + Service. You represent and warrant that you have the necessary rights to upload, store, and process such + data, information, and content using the Service and that your use of the Service complies with all + applicable laws, regulations, and industry standards. +
+By subscribing to Capt’n.ai, you agree to the following terms and conditions:
++ If you have any questions about your Capt’n.ai subscription or these terms, please reach out to us at{' '} + + support@captn.ai + + . +
++ By signing up or creating an account on this website, you agree to receive marketing emails from us, + unless you choose to unsubscribe. These emails may include promotional offers, product updates, + newsletters, or other information related to our services. We value your privacy and assure you that your + email address and personal information will be handled in accordance with our Privacy Policy. +
++ If you wish to unsubscribe from our marketing emails, you can do so by clicking the "unsubscribe" link + provided at the bottom of each email. Please note that even if you unsubscribe from marketing emails, you + may still receive transactional or account-related communications regarding your use of our services. +
++ "Confidential Information" means any information disclosed by either party to the other party that is + marked as confidential or should reasonably be considered confidential given the nature of the information + and the circumstances of its disclosure. +
++ The recipient of Confidential Information will maintain the confidentiality of the Confidential + Information and will not disclose it to any third party, except as necessary to provide the Service or as + required by law. +
++ Either party may terminate these Terms upon written notice to the other party if the other party breaches + any material term of these Terms and fails to cure such breach within thirty (30) days of receiving + written notice of the breach. +
++ Upon termination of these Terms, you must immediately cease all use of the Service and destroy all copies + of the Service in your possession. +
++ We will maintain certain data that you transmit to the Site for the purpose of managing the performance of + the Site, as well as data relating to your use of the Site. Although we perform regular routine backups of + data, you are solely responsible for all data that you transmit or that relates to any activity you have + undertaken using the Site. You agree that we shall have no liability to you for any loss or corruption of + any such data, and you hereby waive any right of action against us arising from any such loss or + corruption of such data. +
++ The Service is provided "as is" and "as available" without any warranties of any kind, whether express or + implied. +
++ We do not warrant that the Service will be uninterrupted or error-free, or that the Service will meet your + requirements or expectations. +
++ We expressly disclaim any and all warranties of merchantability, fitness for a particular purpose, + non-infringement, and any warranties arising out of course of dealing or usage of trade. +
++ The Site may contain (or you may be sent via the Site) links to other websites ("Third-Party Websites") as + well as articles, photographs, text, graphics, pictures, designs, music, sound, video, information, + applications, software, and other content or items belonging to or originating from third parties + ("Third-Party Content"). Such Third-Party Websites and Third-Party Content are not investigated, + monitored, or checked for accuracy, appropriateness, or completeness by us, and we are not responsible for + any Third-Party Websites accessed through the Site or any Third-Party Content posted on, available + through, or installed from the Site, including the content, accuracy, offensiveness, opinions, + reliability, privacy practices, or other policies of or contained in the Third-Party Websites or the + Third-Party Content. Inclusion of, linking to, or permitting the use or installation of any Third-Party + Websites or any Third-Party Content does not imply approval or endorsement thereof by us. If you decide to + leave the Site and access the Third-Party Websites or to use or install any Third-Party Content, you do so + at your own risk, and you should be aware these Terms of Use no longer govern. You should review the + applicable terms and policies, including privacy and data gathering practices, of any website to which you + navigate from the Site or relating to any applications you use or install from the Site. Any purchases you + make through Third-Party Websites will be through other websites and from other companies, and we take no + responsibility whatsoever in relation to such purchases which are exclusively between you and the + applicable third party. You agree and acknowledge that we do not endorse the products or services offered + on Third-Party Websites and you shall hold us harmless from any harm caused by your purchase of such + products or services. Additionally, you shall hold us harmless from any losses sustained by you or harm + caused to you relating to or resulting in any way from any Third-Party Content or any contact with + Third-Party Websites. +
++ In order to receive further information regarding use of the Site, please contact us at:{' '} + + support@captn.ai + + . +
+{state === 'signup' ? titles.signup : titles.login}
+{message}
+{notificationMsg}
+