Skip to content

Commit

Permalink
Deploye code on server
Browse files Browse the repository at this point in the history
jayeshsojitra103 committed Aug 7, 2022
0 parents commit 90ce6b8
Showing 29 changed files with 564,755 additions and 0 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_KEY=5a959352d3add0d42973a2030ce55ff1
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
32 changes: 32 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM node:16-alpine

WORKDIR /app

COPY package.json ./
RUN yarn install

COPY next.config.js ./next.config.js

CMD ["yarn", "dev"]
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Demo

[https://next-weather-au1cr8v3n-jayeshsimform.vercel.app/](https://next-weather-au1cr8v3n-jayeshsimform.vercel.app/)

## Getting Started

First, run the Docker Command: This command will create an image and start continer service on giver port

```bash
docker-compose up
# or
## -d we can start up the container and could use the console after startup for other commands.
docker-compose up -d

##Stop Container
docker-compose down
```

run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
41 changes: 41 additions & 0 deletions component/HourlyWeather.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from "react";
import moment from "moment-timezone";
import Image from "next/image";
const HourlyWeather = ({ hourlyWeather, timezone }) => {
if (timezone) {
return (
<div>
<div className="hourly">
<div className="hourly__inner">
{hourlyWeather?.length > 0 &&
hourlyWeather?.map((weather, index) => (
<div className="hourly__box-wrapper" key={weather?.dt}>
<div className="hourly__box">
<span
className={`hourly__time ${index == 0 ? "hourly__time--now" : ""
}`}
>
{index == 0
? "Now"
: moment.unix(weather?.dt).tz(timezone).format("LT")}
</span>

<Image
src={`https://openweathermap.org/img/wn/${weather?.weather[0]?.icon}@2x.png`}
alt={weather?.weather[0]?.description}
width="100"
height="100"
/>

<span>{weather?.temp.toFixed(0)}&deg;C</span>
</div>
</div>
))}
</div>
</div>
</div>
);
}

}
export default HourlyWeather;
81 changes: 81 additions & 0 deletions component/SearchBox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useState, useEffect } from "react";
import cities from "../lib/city.list.json";
import Link from "next/link";
import Router from "next/router";


const SearchBox = ({ placeholder }) => {
const [query, setQuery] = useState("");
const [result, setResult] = useState([]);

useEffect(() => {
const clearQuery = () => setQuery("");
Router.events.on("routeChangeComplete", clearQuery);

return () => {
Router.events.on("routeChangeComplete", clearQuery);
};
}, []);

//Search City name
const onSearchCityChange = (e) => {
const { value } = e.target;
setQuery(value);
let matchingCities = [];
if (value.length > 3) {
for (let city of cities) {
if (matchingCities.length >= 5) {
break;
}
const match = city?.name
?.toLowerCase()
?.startsWith(value?.toLowerCase());

if (match) {
const cityData = {
...city,
slug: `${city.name.toLowerCase().replace(/ /g, "-")}-${city.id}`,
};
matchingCities.push(cityData);
}
}
}
return setResult(matchingCities);
};


return (
<div className="search">
<input
placeholder={placeholder ? placeholder : ""}
type="text"
value={query}
onChange={onSearchCityChange}
/>
{query?.length > 3 && (
<ul>
{result?.length > 0 ? (
result.map((city) => {
return (
<li key={city?.slug}>
<Link href={`/location/${city?.slug}`}>
<a>
{city?.name}
{city?.state ? `-,${city?.state}` : ""}
-
<span>{city?.country}</span>
</a>
</Link>
</li>
);
})
) : (
<li className="search__no_results">No Results found</li>
)}
</ul>
)}
</div>
);
}

export default SearchBox;
54 changes: 54 additions & 0 deletions component/TodaysWeather.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from "react";
import moment from "moment-timezone";
import Image from "next/image";

const TodaysWeather = ({ city, weather, timezone }) => {
if (timezone) {
return (
<div className="today">
<div className="today__inner">
<div className="today__left-content">
<h1>
{city?.name} {city?.country}
</h1>

<h2>
<span>{weather?.temp?.max?.toFixed(0)}&deg;C</span>
<span>{weather?.temp?.min?.toFixed(0)}&deg;C</span>
</h2>

<div className="today__sun-times">
<div>
<span>Sunrise</span>
<span>
{moment.unix(weather?.sunrise).tz(timezone)?.format("LT")}
</span>
</div>
<div>
<span>Sunset</span>
<span>
{moment.unix(weather?.sunset).tz(timezone)?.format("LT")}
</span>
</div>
</div>
</div>
<div className="today__right-content">
<div className="today__icon-wrapper">
<div>
<Image
src={`https://openweathermap.org/img/wn/${weather?.weather[0]?.icon}@2x.png`}
alt="Waether Icon"
layout="fill"
/>
</div>
</div>
<h3>{weather?.weather[0]?.description}</h3>
</div>
</div>
</div>
);
}

}

export default TodaysWeather;
73 changes: 73 additions & 0 deletions component/WeeklyWeather.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from "react";
import moment from "moment-timezone";
import Image from "next/image";

const WeeklyWeather = ({ weeklyWeather, timezone }) => {
if (timezone) {
return (
<div className="weekly">
<h3 className="weekly__title">
Weekly <span>Weather</span>
</h3>

{weeklyWeather.length > 0 &&
weeklyWeather.map((weather, index) => {
if (index == 0) {
return;
}

return (
<div className="weekly__card" key={weather?.dt}>
<div className="weekly__inner">
<div className="weekly__left-content">
<div>
<h3>
{moment.unix(weather?.dt).tz(timezone).format("dddd")}
</h3>

<h4>
<span>{weather?.temp?.max?.toFixed(0)}&deg;C</span>
<span>{weather?.temp?.min?.toFixed(0)}&deg;C</span>
</h4>
</div>

<div className="weekly__sun-times">
<div>
<span>Sunrise</span>
<span>
{moment.unix(weather?.sunrise).tz(timezone).format("LT")}
</span>
</div>

<div>
<span>Sunset</span>
<span>
{moment.unix(weather?.sunset).tz(timezone).format("LT")}
</span>
</div>
</div>
</div>

<div className="weekly__right-content">
<div className="weekly__icon-wrapper">
<div>
<Image
src={`https://openweathermap.org/img/wn/${weather?.weather[0]?.icon}@2x.png`}
alt="Weather Icon"
layout="fill"
/>
</div>
</div>

<h5>{weather?.weather[0]?.description}</h5>
</div>
</div>
</div>
);
})}
</div>
);
}

}
export default WeeklyWeather;
16 changes: 16 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: '3'

services:
app:
image: next-weather-app
build: .
ports:
- 3000:3000
volumes:
- ./pages:/app/pages
- ./public:/app/public
- ./styles:/app/styles
- ./component:/app/component
- ./lib:/app/lib
env_file:
- ./.env.local
557,767 changes: 557,767 additions & 0 deletions lib/city.list.json

Large diffs are not rendered by default.

Empty file added lib/index.js
Empty file.
10 changes: 10 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require("dotenv").config();
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
domains: ["openweathermap.org"],
},
}

module.exports = nextConfig
5,940 changes: 5,940 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "next-weather-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "set NODE_OPTIONS=--max-old-space-size=8192 && next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"dotenv": "^16.0.1",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"next": "12.1.6",
"nprogress": "^0.2.0",
"react": "18.1.0",
"react-dom": "18.1.0",
"sass": "^1.51.0"
},
"devDependencies": {
"@swc/cli": "^0.1.57",
"@swc/core": "^1.2.224",
"eslint": "^8.15.0",
"eslint-config-next": "12.1.6",
"eslint-plugin-react": "^7.30.1"
}
}
8 changes: 8 additions & 0 deletions pages/404.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const NotFound = () => {
return (
<div>
NotFound
</div>
);
}
export default NotFound;
22 changes: 22 additions & 0 deletions pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { useEffect } from "react";
import nprogress from "nprogress";
import Router from "next/router";
import "../styles/main.scss";
function MyApp({ Component, pageProps }) {
useEffect(() => {
const start = () => nprogress.start();
const end = () => nprogress.done();
Router.events.on("routeChangeStart", start);
Router.events.on("routeChangeComplete", end);
Router.events.on("routeChangeError", end);
return () => {
Router.events.on("routeChangeStart", start);
Router.events.on("routeChangeComplete", end);
Router.events.on("routeChangeError", end);
};
}, []);

return <Component {...pageProps} />;
}

export default MyApp;
5 changes: 5 additions & 0 deletions pages/api/hello.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction

export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' });
}
20 changes: 20 additions & 0 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Head from "next/head";
import SearchBox from "../component/SearchBox";


export default function Home() {
return (
<div>

<Head>
<title>Weather App - Next</title>
</Head>

<div className="home">
<div className="container">
<SearchBox placeholder="Search for a city..." />
</div>
</div>
</div>
);
}
102 changes: 102 additions & 0 deletions pages/location/[city].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from "react";
import cities from "../../lib/city.list.json";
import moment from "moment-timezone";
import Link from "next/link";
import Error from 'next/error'
import TodaysWeather from "../../component/TodaysWeather";
import HourlyWeather from "../../component/HourlyWeather";
import WeeklyWeather from "../../component/WeeklyWeather";
import SearchBox from "../../component/SearchBox";
import Head from "next/head";

export async function getServerSideProps(context) {
const city = getCity(context?.params?.city);
if (!city) {
return {
notFound: true,
};
}
const res = await fetch(
`https://api.openweathermap.org/data/2.5/onecall?lat=${city?.lat}&lon=${city?.lng}&appid=${process.env.API_KEY}&exclude=minutely&units=metric`
);
const data = await res?.json();
const errorCode = res?.ok ? false : res?.status;

if (!data) {
return {
notFound: true,
};
}

const hourlyWeather = getHourlyWeather(data?.hourly, data?.timezone);
return {
props: {
errorCode,
errorMessage: res?.statusText,
city: city,
dailyWeather: data?.daily || {},
hourlyWeather: hourlyWeather || {},
timezone: data?.timezone || '',
}
};
}


const getCity = (param) => {
const cityParam = param.trim();
// get the id of the city
const splitCity = cityParam.split("-");
const id = splitCity[splitCity.length - 1];
if (!id) {
return null;
}
const city = cities.find((city) => city.id.toString() === id);
if (city) {
return city;
} else {
return null;
}
};

const getHourlyWeather = (hourlyData, timezone) => {
if (timezone) {
const endofDay = moment().tz(timezone).endOf("day").valueOf();
const endTimeStamp = Math.floor(endofDay / 1000);

const todaysData = hourlyData.filter((data) => data.dt < endTimeStamp);

return todaysData;
}

};

const City = ({ city, timezone, dailyWeather, hourlyWeather, errorCode, errorMessage }) => {

if (errorCode) {
return <Error statusCode={errorCode} title={errorMessage} />;
}
return (
<div>
<Head>
<title>{city.name} Weather - Next Weather App</title>
</Head>
<div className="page-wrapper">
<div className="container">
<Link href="/">
<span className="back-link">&larr; Home</span>
</Link>
<SearchBox placeholder="Search for another location" />

<TodaysWeather
city={city}
weather={dailyWeather[0]}
timezone={timezone}
/>
<HourlyWeather hourlyWeather={hourlyWeather} timezone={timezone} />
<WeeklyWeather weeklyWeather={dailyWeather} timezone={timezone} />
</div>
</div>
</div>
);
}
export default City;
Binary file added public/favicon.ico
Binary file not shown.
Binary file added public/images/bg.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/london.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/new-york.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/paris.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/tokyo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
510 changes: 510 additions & 0 deletions styles/main.scss

Large diffs are not rendered by default.

1 comment on commit 90ce6b8

@vercel
Copy link

@vercel vercel bot commented on 90ce6b8 Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.