Skip to content

kweeuhree/climate-view

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

Climate View

This repository contains code for a full stack application meant to provide an overview of Earth's climate state as of 2024. The app is following an MVC(Model-View-Controller) architecture.

Users can create an account and leave comments once logged in. The application keeps track of days since the user joined.

Stack:

  • MongoDB - backend database solution
  • Express.js - backend framework that handles middleware calls
  • React.js - frontend library for creating a user interface
  • Node.js - JavaScript runtime environment

Backend

APIs are created following best practices of REST.

Express simplifies creation of server-side logic and handles middleware calls. Express routers are looking for a request body params to simplify extraction of User or Comment ID:
router.param('id', async (req, res, next, id) => {
  try {
  const found = await User.findById(id);
   if (found) {
  //if user exists assign their id to userId
   req.userId = id;
   next(); // call next function
  } else { // if id doesn't exist send 404 status
    res.status(404).send('User not found');
   }
  } catch (error) {
    res.status(500);
  }
 });

User authorization is performed using a cookie parser, JWT and bcrypt.


Mongoose is used for an efficient data modeling.

MongoDB is used to ensure persistance of user profiles and user comments. Full CRUD system is set up to allow users read, create, update and delete comments that are attached to their user ID.



Frontend

React.js is used to create modular code with reusable components. Examples: ImageContainer, ImageSliderContainer, Header. Pages, as well as utils, are separated from components for maitenance purposes.

Animations, gifs, videos, and images are used throughout the application in order to provide better user experience.

Intro component is using useEffect in order to fire off a timer that will trigger a soft appearrance of text. Onmount of the component, the timer will trigger dynamic style application, clean up function ensures proper memory management by clearing the timer:
 const [loaded, setLoaded] = useState(false);
 useEffect(() => {
  const timer = setTimeout(() => {
  setLoaded(true); // trigger new style
 }, 150);
  return () => clearTimeout(timer);
 }, []);  

className={`intro-text ${loaded ? 'fade-in' : ''}`}

ImageSliderContainer is created with react-compare-image library to streamline the development process. Inside ImageSliderContainer hover effects are achieved thorugh state. Hovered state is initialized as false, state is watching for a mouse action, which triggers changes in state, and consequently produces a hover effect:
const [isHovered, setIsHovered] = useState(false);
 onMouseEnter={()=>setIsHovered(true)}
 onMouseLeave={()=>setIsHovered(false)}


Atmosphere component is relying on useRef, useEffect and IntersectionObserver to track the component being scrolled into view, which consequently triggers animations within the component, clean up function ensures that we stop observing in order to prevent memory leaks:
 const [isInView, setIsInView] = useState(false);
 const imagesParentRef = useRef(null);
 useEffect(() => {
  const observer = new IntersectionObserver((entries) => {
   entries.forEach((entry) => {
   (entry.isIntersecting) {
   setIsInView(true);
   observer.unobserve(entry.target);
  }
  });
 });
 if (imagesParentRef.current) {
  observer.observe(imagesParentRef.current);
 }
  return () => { // clean up
  if (imagesParentRef.current) {
  observer.unobserve(imagesParentRef.current);
  }
 };
 }, []);

className={`image-parent ${isInView ? 'animate' : ''}`}


HistoryPage component is using data fetched from open-meteo.com and displays cities that user picks. Application is interacting with the user via a form. State and Country parameters are made optional in order to let user pick how they want to search their location. Behind the hood, the app will capitalize user input in order to make state and country optional.
Picked city is added to a comparison container, which is also happening thorugh state of currently picked city, as well as both cities. Once cities array stops being empty, Cities component will display city/cities:
 const [city, setCity] = useState({
  id: '',
  stateRegion: '',
  country: '',
  name: '',
  date: '',
  temp: ''
 })

 const [cities, setCities] = useState([]);

 cities?.length > 0 ? (
  < Cities cities={cities} removeCity={removeCity} /> )




ProfilePage tracks days dince joining and allows to log out and delete account.