Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sweep: Refactor Footer, Navbar, and PricingModal to class components #435

Open
3 tasks done
Tracked by #335
sweep-nightly bot opened this issue Aug 24, 2023 · 1 comment · May be fixed by #439
Open
3 tasks done
Tracked by #335

Sweep: Refactor Footer, Navbar, and PricingModal to class components #435

sweep-nightly bot opened this issue Aug 24, 2023 · 1 comment · May be fixed by #439
Assignees
Labels

Comments

@sweep-nightly
Copy link
Contributor

sweep-nightly bot commented Aug 24, 2023

  • In src/components/Footer.tsx, refactor the Footer function into a class component.
  • In src/components/Navbar.tsx, refactor the Navbar function into a class component.
  • In src/components/PricingModal.tsx, refactor the PricingModal function into a class component.

Parent issue: #335

Checklist
  • src/components/Footer.tsx

• Change the Footer function into a class component named Footer.
• Move the JSX returned by the Footer function into the render method of the Footer class.

  • src/components/Navbar.tsx

• Change the Navbar function into a class component named Navbar.
• Move the JSX returned by the Navbar function into the render method of the Navbar class.

  • src/components/PricingModal.tsx

• Change the PricingModal function into a class component named PricingModal.
• Move the JSX returned by the PricingModal function into the render method of the PricingModal class.

@sweep-nightly
Copy link
Contributor Author

sweep-nightly bot commented Aug 24, 2023

Here's the PR! #439.

💎 Sweep Pro: I used GPT-4 to create this ticket. You have unlimited GPT-4 tickets. To retrigger Sweep, edit the issue.


Step 1: 🔍 Code Search

I found the following snippets in your repository. I will now analyze these snippets and come up with a plan.

Some code snippets I looked at (click to expand). If some file is missing from here, you can mention the path in the ticket description.

import { useState } from 'react';
import { Text, Modal, Button, ModalBody, ModalFooter, ModalOverlay, ModalContent, SimpleGrid, Box } from '@chakra-ui/react';
// import { MdDiamond } from "react-icons/md";
export default function PricingModal() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button onClick={handleShow}>
Pricing
</Button>
<Modal isOpen={show} onClose={handleClose} size="5xl">
<ModalOverlay />
<ModalContent p={8} backgroundColor="#0d1117" pb={4}>
<ModalBody>
<SimpleGrid columns={{ base: 1, md: 3 }} spacing={10}>
<Box
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="space-between"
height="100%"
>
<Box>
<Text fontSize="lg" mb={2} textAlign="center">
⚡ Basic
</Text>
<Text fontSize="4xl" mb="4" fontWeight="bold" textAlign="center">
Free
</Text>
<Box as="ul" style={{ listStyleType: 'none' }}>
<li>✔ 5 GPT-4 Sweep tickets / month</li>
<li>✔ Unlimited GPT-3.5 Sweep issues</li>
<br />
<li>
<Button colorScheme="purple" onClick={() => window.open("https://buy.stripe.com/7sI4jlaCR3PaabebIP", "_blank")}>
Extended trial
</Button>
&nbsp;- make a <b>one-time purchase</b> of 15 additional PRs
</li>
</Box>
</Box>
<Button colorScheme="purple" mt={12} onClick={() => window.open("https://github.com/sweepai/sweep#-getting-started", "_blank")}>
Install
</Button>
</Box>
<Box display="flex" flexDirection="column" alignItems="center" justifyContent="space-between" height="100%">
<Box>
<Text fontSize="lg" mb={2} textAlign="center">
💎 Pro
</Text>
<Text fontSize="4xl" mb="4" fontWeight="bold" textAlign="center">
$480 <span style={{ fontWeight: "normal" }}>/ month</span>
</Text>
<Box as="ul" style={{ listStyleType: 'none' }}>
<li>✔ Unlimited GPT-4 Sweep issues</li>
<li>✔ Faster search with live re-indexing</li>
<li>✔ Priority support</li>
<li>✔ Commercial SLA</li>
</Box>
</Box>
<Button colorScheme="purple" mt={12} onClick={() => window.open("https://buy.stripe.com/6oE5npbGVbhC97afZ4", "_blank")}>
Purchase
</Button>
</Box>
<Box display="flex" flexDirection="column" alignItems="center" justifyContent="space-between" height="100%">
<Box>
<Text fontSize="lg" mb={2} textAlign="center">
🏢 Enterprise
</Text>
<Text fontSize="4xl" mb="4" fontWeight="bold" textAlign="center">
Custom
</Text>
<Box as="ul" style={{ listStyleType: 'none' }}>
<li>✔ Unlimited GPT-4 Sweep issues</li>
<li>✔ Fine-tuned retrieval model</li>
<li>✔ Self-hosted backend</li>
<li>✔ Enterprise support</li>
</Box>
</Box>
<Button colorScheme="purple" mt={12} onClick={() => window.open("https://form.typeform.com/to/wliuvyWE", "_blank")}>
Contact us
</Button>
</Box>
</SimpleGrid>
</ModalBody>
<ModalFooter display="flex" alignItems="center" flexDirection="column">
<Button variant="ghost" onClick={handleClose} mt={4}>
</Button>
</ModalFooter>
</ ModalContent>
</Modal >
</>

import { EmailIcon, HamburgerIcon } from "@chakra-ui/icons";
import PricingModal from './PricingModal';
import {
Box,
Button,
ButtonGroup,
Flex,
HStack,
IconButton,
Image,
Menu,
MenuButton,
MenuItem,
MenuList,
useBreakpointValue,
} from "@chakra-ui/react";
import { Link } from 'react-router-dom';
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
import logo from "../assets/icon.png";
export default function NavBar() {
const listDisplay = useBreakpointValue({ base: "none", lg: "flex" });
const menuDisplay = useBreakpointValue({ base: "flex", lg: "none" });
const navItems = [
{
label: "Twitter",
icon: <FaTwitter />,
link: "https://twitter.com/sweep__ai",
},
{
label: "Github",
icon: <FaGithub />,
link: "https://github.com/sweepai/sweep",
},
{
label: "Discord",
icon: <FaDiscord />,
link: "https://discord.gg/sweep",
},
{
label: "Email",
icon: <EmailIcon />,
link: "mailto:team@sweep.dev",
},
// {
// label: "Buy Sweep Pro",
// icon: <p>Buy Sweep Pro</p>,
// link: "https://buy.stripe.com/fZe03512h99u0AE6os",
// },
];
return (
<Box as="nav" bg="bg-surface" boxShadow="sm" width="full" p={4}>
<HStack spacing="10" justify="space-between">
<Flex justify="space-between" flex="1">
<HStack>
<Button variant="ghost">
<Image src={logo} alt="logo" width={10} borderRadius={12} />
Sweep AI
</Button>
<Button variant="ghost" onClick={() => window.open("https://docs.sweep.dev", "_blank")}>
Documentation
</Button>
<Link to="/about-us">
<Button variant="ghost">
About Us
</Button>
</Link>
{/* Removed conditional rendering of PricingModal */}
</HStack>
<ButtonGroup variant="link" display={listDisplay}>
{navItems.map((item) => (
<IconButton
key={item.label}
icon={item.icon}
variant="ghost"
aria-label={item.label}
onClick={() => {
window.open(item.link, "_blank");
}}
px={2}
/>
))}
{/* Added PricingModal to always be displayed */}
<PricingModal />
</ButtonGroup>
<Menu>
<MenuButton
as={IconButton}
aria-label='Options'
icon={<HamburgerIcon />}
variant='outline'
display={menuDisplay}
/>
<MenuList
backgroundColor="#333"
>
{navItems.map((item) => (
<MenuItem backgroundColor="#333">
{item.label}
{
item.label !== "Buy Sweep Pro" &&
<IconButton
key={item.label}
icon={item.icon}
variant="ghost"
aria-label={item.label}
onClick={() => {
window.open(item.link, "_blank");
}}
/>
}
</MenuItem>
))}
</MenuList>
</Menu>
</Flex>
</HStack>
</Box>

import { Box, Link, Stack } from "@chakra-ui/react";
import YCLogo from "../assets/yc.webp";
export default function Footer() {
return (
<Box as="footer" py={4}>
<Stack direction={{ base: "column", md: "row" }} spacing={4} align="center" justify="center" fontSize={"sm"} my={{ base: 4, md: 0 }}>
<Link href="https://github.com/sweepai" textAlign={{ base: "center", md: "left" }}>Github</Link>
<Link href="https://discord.gg/j8XxQmpHEF" textAlign={{ base: "center", md: "left" }}>Discord</Link>
<Link href="https://docs.sweep.dev" textAlign={{ base: "center", md: "left" }}>Docs</Link>
<Link href="https://buy.stripe.com/6oE5npbGVbhC97afZ4" textAlign={{ base: "center", md: "left" }}>Sweep Pro</Link>
<Link href="https://ycombinator.com/companies/sweep" target="_blank" rel="noopener noreferrer" display="inline-flex" alignItems="center" textAlign={{ base: "center", md: "left" }}>
Backed by <img src={YCLogo} alt="Y Combinator" style={{ marginLeft: "10px" }} height="10px" />
</Link>
</Stack>
</Box>

landing-page/src/App.tsx

Lines 1 to 104 in 836113d

import {
ChakraProvider,
Box,
extendTheme,
useColorMode,
ThemeConfig,
} from "@chakra-ui/react";
import CallToAction from "./components/CallToAction";
import { Helmet } from "react-helmet";
import Navbar from "./components/Navbar";
import Banner from "./components/Banner";
import og_image from "./assets/og_image.png";
import { ColorModeSwitcher } from "./ColorModeSwitcher";
import { useEffect } from "react";
import Testimonials from "./components/Testimonials";
import Users from "./components/Users";
import AboutUs from "./components/AboutUs";
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import circles from "./assets/circles.svg";
import Features from "./components/Features";
import Conclusion from "./components/Conclusion";
const config: ThemeConfig = {
initialColorMode: "dark",
useSystemColorMode: false,
};
const theme = extendTheme({ config });
function ForceDarkMode(props: { children: JSX.Element }) {
const { colorMode, toggleColorMode } = useColorMode();
useEffect(() => {
if (colorMode === "dark") return;
toggleColorMode();
}, [colorMode, toggleColorMode]);
return props.children;
}
// @ts-ignore
window.intercomSettings = {
api_base: "https://api-iam.intercom.io",
app_id: "ce8fl00z",
action_color: "#6b46c1",
background_color: "#342867",
};
export const App = () => {
useEffect(() => {
const script = document.createElement("script");
script.type = "text/javascript";
script.async = true;
script.innerHTML = `(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/ce8fl00z';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;
document.body.appendChild(script);
}, []);
return (
<>
<Helmet>
<meta property="og:image" content={og_image} />
<link rel="icon" type="image/png" sizes="16x16" href="/final-sweep-wizard_16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/final-sweep-wizard_32x32.png" />
<link rel="icon" type="image/png" sizes="48x48" href="/final-sweep-wizard_48x48.png" />
<link rel="icon" type="image/png" sizes="64x64" href="/final-sweep-wizard_64x64.png" />
<link rel="icon" type="image/png" sizes="128x128" href="/final-sweep-wizard_128x128.png" />
<link rel="icon" type="image/png" sizes="256x256" href="/final-sweep-wizard_256x256.png" />
</Helmet>
<ChakraProvider theme={theme}>
<ForceDarkMode>
<Box
textAlign="center"
fontSize="xl"
bgColor="#0d0a1a"
bgImage={circles}
bgPos="0 0"
bgSize="100%"
minH="100vh"
bgRepeat="no-repeat"
overflowX="hidden"
>
{false && <ColorModeSwitcher />}
<Banner />
<Router>
<Navbar />
<Switch>
<Route exact path="/">
<CallToAction />
<Users />
<Features />
<Testimonials />
<Conclusion />
</Route>
<Route path="/about-us">
<AboutUs />
</Route>
</Switch>
</Router>
</Box>
</ForceDarkMode>
</ChakraProvider>
</>
);

import * as React from "react"
import { render, RenderOptions } from "@testing-library/react"
import { ChakraProvider, theme } from "@chakra-ui/react"
const AllProviders = ({ children }: { children?: React.ReactNode }) => (
<ChakraProvider theme={theme}>{children}</ChakraProvider>
)
const customRender = (ui: React.ReactElement, options?: RenderOptions) =>
render(ui, { wrapper: AllProviders, ...options })


Step 2: 🧐 Snippet Analysis

From looking through the relevant snippets, I decided to make the following modifications:

File Path Proposed Changes
src/components/Footer.tsx Modify src/components/Footer.tsx with contents:
• Change the Footer function into a class component named Footer.
• Move the JSX returned by the Footer function into the render method of the Footer class.
src/components/Navbar.tsx Modify src/components/Navbar.tsx with contents:
• Change the Navbar function into a class component named Navbar.
• Move the JSX returned by the Navbar function into the render method of the Navbar class.
src/components/PricingModal.tsx Modify src/components/PricingModal.tsx with contents:
• Change the PricingModal function into a class component named PricingModal.
• Move the JSX returned by the PricingModal function into the render method of the PricingModal class.

Step 3: 📝 Planning

I have created a plan for writing the pull request. I am now working my plan and coding the required changes to address this issue. Here is the planned pull request:

Refactor Footer, Navbar, and PricingModal to class components
sweep/refactor-class-components

Description

This PR refactors the Footer, Navbar, and PricingModal components from functional components to class components in order to align with the requirements of the issue #435. The refactoring involves changing the syntax and structure of the components to use class-based components in React.

Summary

  • Refactored the Footer component into a class component named Footer.
  • Moved the JSX returned by the Footer function into the render method of the Footer class.
  • Refactored the Navbar component into a class component named Navbar.
  • Moved the JSX returned by the Navbar function into the render method of the Navbar class.
  • Refactored the PricingModal component into a class component named PricingModal.
  • Moved the JSX returned by the PricingModal function into the render method of the PricingModal class.

Please review and merge these changes. Thank you!


Step 4: ⌨️ Coding

File Instructions Progress Error logs
src/components/Footer.tsx Modify src/components/Footer.tsx with contents:
• Change the Footer function into a class component named Footer.
• Move the JSX returned by the Footer function into the render method of the Footer class.
✅ Commit 836113d No errors.
src/components/Navbar.tsx Modify src/components/Navbar.tsx with contents:
• Change the Navbar function into a class component named Navbar.
• Move the JSX returned by the Navbar function into the render method of the Navbar class.
✅ Commit 6511b33 No errors.
src/components/PricingModal.tsx Modify src/components/PricingModal.tsx with contents:
• Change the PricingModal function into a class component named PricingModal.
• Move the JSX returned by the PricingModal function into the render method of the PricingModal class.
✅ Commit 6511b33 No errors.

Step 5: 🔁 Code Review

Here are my self-reviews of my changes at sweep/refactor-class-components_5.

Here is the 1st review

Good job on refactoring the function components into class components. However, there is a small issue in the Navbar component that needs to be addressed.

In the src/components/Navbar.tsx file, the responsiveness of the NavBar might not work as expected because the window resize event is not being listened to update the state variables listDisplay and menuDisplay. This can be fixed by adding an event listener for the window resize event in the componentDidMount lifecycle method and updating the state variables accordingly.

Here is a sample code snippet for the componentDidMount method:

componentDidMount() {
  window.addEventListener('resize', this.handleResize);
}

handleResize = () => {
  this.setState({
    listDisplay: window.innerWidth > 1024 ? "flex" : "none",
    menuDisplay: window.innerWidth <= 1024 ? "flex" : "none",
  });
};

Don't forget to remove the event listener in the componentWillUnmount method to avoid memory leaks:

componentWillUnmount() {
  window.removeEventListener('resize', this.handleResize);
}

Keep up the good work!

I finished incorporating these changes.


🎉 Latest improvements to Sweep:

  • Use Sweep Map to break large issues into smaller sub-issues, perfect for large tasks like "Sweep (map): migrate from React class components to function components"
  • Getting Sweep to format before committing! Check out Sweep Sandbox Configs to set it up.
  • We released a demo of our chunker, where you can find the corresponding blog and code.

💡 To recreate the pull request edit the issue title or description.
Join Our Discord

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant