├── src
├── index.css
├── components
│ ├── images
│ │ ├── coron-map.jpg
│ │ └── suggested-itinerary-palawan-philippines.jpg
│ ├── Forecast.js
│ ├── NavBar.js
│ ├── LogInForm.js
│ ├── Weather.js
│ ├── picsforapp.js
│ ├── BackgroundSlider.js
│ ├── SignUpForm.js
│ └── data.js
├── setupTests.js
├── App.test.js
├── reportWebVitals.js
├── utilities
│ ├── plan-service.js
│ ├── plan-api.js
│ ├── users-service.js
│ └── users-api.js
├── index.js
├── pages
│ ├── AuthPage.js
│ ├── SavedItineraries.js
│ └── Itinerary.js
├── App.css
├── logo.svg
└── App.js
├── Procfile
├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── .env
├── config
├── ensureLoggedIn.js
├── database.js
└── checkToken.js
├── .gitignore
├── routes
└── api
│ ├── users.js
│ └── plan.js
├── models
├── plan.js
└── user.js
├── README2.md
├── server.js
├── controllers
└── api
│ ├── users.js
│ └── plan.js
├── package.json
└── README.md
/src/index.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: node server.js
2 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaNeliaTerrell/TravelPlanningApp/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaNeliaTerrell/TravelPlanningApp/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaNeliaTerrell/TravelPlanningApp/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/src/components/images/coron-map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaNeliaTerrell/TravelPlanningApp/HEAD/src/components/images/coron-map.jpg
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | DATABASE_URL=mongodb+srv://NTerrell:Poohnate2709@sei.slk3o4k.mongodb.net/TravelPlanningApp?retryWrites=true&w=majority
2 |
3 | SECRET=Hello
--------------------------------------------------------------------------------
/src/components/images/suggested-itinerary-palawan-philippines.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaNeliaTerrell/TravelPlanningApp/HEAD/src/components/images/suggested-itinerary-palawan-philippines.jpg
--------------------------------------------------------------------------------
/config/ensureLoggedIn.js:
--------------------------------------------------------------------------------
1 | module.exports = function(req, res, next) {
2 | // Status code of 401 is Unauthorized
3 | if (!req.user) return res.status(401).json('Unauthorized');
4 | // A okay
5 | next();
6 | };
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render( );
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/config/database.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | mongoose.connect(process.env.DATABASE_URL)
4 |
5 | const db = mongoose.connection;
6 |
7 | db.on('connected', function () {
8 | console.log(`Connected to ${db.name} at ${db.host}:${db.port}`);
9 | });
10 |
11 | module.exports = mongoose;
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 | .env
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/utilities/plan-service.js:
--------------------------------------------------------------------------------
1 | // import * as planAPI from './plan-api'
2 |
3 | // export async function savingData(savedPlan) {
4 | // // Delegate the network request code to the users-api.js API module
5 | // // which will ultimately return a JSON Web Token (JWT)
6 | // const dayPlan = await planAPI.savingData(savedPlan);
7 |
8 | // // Baby step by returning whatever is sent back by the server
9 | // // return token;
10 | // localStorage.setItem('dayPlan', dayPlan)
11 | // }
12 |
--------------------------------------------------------------------------------
/routes/api/users.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const usersCtrl = require('../../controllers/api/users');
3 | const router = express.Router();
4 |
5 |
6 | const ensureLoggedIn = require('../../config/ensureLoggedIn');
7 | // POST /api/users
8 |
9 | // router.post('/', (req, res) => {
10 | // })
11 |
12 | // GET /api/users/check-token
13 | router.get('/check-token', ensureLoggedIn, usersCtrl.checkToken);
14 |
15 |
16 | // /api/users
17 | router.post('/', usersCtrl.create);
18 |
19 | router.post('/login', usersCtrl.logIn)
20 |
21 |
22 |
23 | module.exports = router
--------------------------------------------------------------------------------
/src/components/Forecast.js:
--------------------------------------------------------------------------------
1 | import Weather from "./Weather"
2 | import '../../src/App.css'
3 |
4 |
5 | const Forecast = (props) => {
6 | const { minTemp, maxTemp, weatherType,date} = props
7 | return(
8 |
9 |
10 |
11 |
Date: {date}
12 |
13 |
Weather Type: {weatherType}
14 |
15 |
Min. Temperature: {minTemp}
16 |
17 | Max. Temperature: {maxTemp}
18 |
19 | )
20 | }
21 | export default Forecast
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/routes/api/plan.js:
--------------------------------------------------------------------------------
1 | // const express = require('express')
2 | // // const planCtrl = require('../../controllers/api/users');
3 | // const router = express.Router();
4 | // const plansCtrl = require('../../controllers/api/plan.js');
5 | // const { route } = require('./users.js');
6 |
7 |
8 | // // POST api/plan create new task
9 | // router.post('/', plansCtrl.savePlan)
10 |
11 | // // GET api/plan ^see all tasks
12 | // router.get('/', plansCtrl.readPlan)
13 |
14 | // // PUT /api/plan/:id ^update the plan
15 | // router.put('/:id', plansCtrl.updatePlan)
16 |
17 | // // DELETE /api/plan/:id
18 |
19 | // router.delete('/:id', plansCtrl.deletePlan)
20 |
21 | // module.exports = router
--------------------------------------------------------------------------------
/models/plan.js:
--------------------------------------------------------------------------------
1 | // const mongoose = require("mongoose")
2 | // const bcrypt = require("bcrypt")
3 | // const Schema = mongoose.Schema
4 | // const SALT_ROUNDS = 6
5 |
6 | // const planSchema = new mongoose.Schema(
7 | // {
8 | // name: {
9 | // type: String,
10 | // required: true
11 | // },
12 | // img: {
13 | // type: String,
14 | // required: true
15 | // },
16 | // location: {
17 | // type: String,
18 | // required: false
19 | // },
20 | // website: {
21 | // type: String,
22 | // required: false
23 | // },
24 | // },
25 | // )
26 |
27 |
28 | // module.exports = mongoose.model('plan', planSchema)
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 |
4 | import './App.css'
5 | import App from './App';
6 | import reportWebVitals from './reportWebVitals';
7 | import { BrowserRouter as Router } from 'react-router-dom';
8 | import 'bootstrap/dist/css/bootstrap.min.css';
9 |
10 | const root = ReactDOM.createRoot(document.getElementById('root'));
11 | root.render(
12 |
13 |
14 |
15 |
16 |
17 | );
18 |
19 | // If you want to start measuring performance in your app, pass a function
20 | // to log results (for example: reportWebVitals(console.log))
21 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
22 | reportWebVitals();
23 |
--------------------------------------------------------------------------------
/src/pages/AuthPage.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import SignUpForm from "../components/SignUpForm"
3 | import LogInForm from '../components/LogInForm'
4 | import '../../src/App.css';
5 | import '../../src/index.css'
6 |
7 |
8 |
9 | const AuthPage = ({ setUser }) => {
10 | const [showSignUp, setShowSignUp] = useState(true);
11 |
12 |
13 | return (
14 |
15 |
16 |
17 |
18 |
19 | {showSignUp ? : }
20 |
21 | setShowSignUp(!showSignUp)} >{showSignUp ? "Log In" : "Sign Up"}
23 |
24 |
25 | <>
26 |
27 |
28 |
29 | >
30 |
31 |
32 |
33 | )
34 | }
35 | export default AuthPage
36 |
--------------------------------------------------------------------------------
/config/checkToken.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken');
2 |
3 | module.exports = function(req, res, next) {
4 | // Check for the token being sent in a header or as a query parameter
5 | let token = req.get('Authorization') || req.query.token;
6 | if (token) {
7 | // Remove the 'Bearer ' if it was included in the token header
8 | token = token.replace('Bearer ', '');
9 | // Check if token is valid and not expired
10 | jwt.verify(token, process.env.SECRET, function(err, decoded) {
11 | // If valid token, decoded will be the token's entire payload
12 | // If invalid token, err will be set
13 | req.user = err ? null : decoded.user;
14 | // If your app cares... (optional)
15 | req.exp = err ? null : new Date(decoded.exp * 1000);
16 | return next();
17 | });
18 | } else {
19 | // No token was sent
20 | req.user = null;
21 | return next();
22 | }
23 | };
--------------------------------------------------------------------------------
/README2.md:
--------------------------------------------------------------------------------
1 | Travel Planning App
2 |
3 | Coron, Palawan, Philippines
4 |
5 | Github Link:
6 | https://github.com/MaNeliaTerrell/TravelPlanningApp
7 |
8 | ## Basic Information
9 |
10 | App shows forecast for 8 days
11 | Sign up/Log in
12 |
13 | User will be able to sign up/log and then choose places, activities, places to eat and places to stay for the day. They are able to modify plans and make decisions based on real-time weather conditions.
14 |
15 | # Wishlist
16 |
17 | Date-picker
18 | Transportation logging system
19 | Flight info
20 | How to get around
21 |
22 |
23 | ## Tech Stack
24 | - Javascript
25 | - HTML
26 | - CSS
27 | - MERN
28 |
29 | ## Unsolved Issues
30 |
31 | Background Slider/Carousel
32 | Unable to Save itinerary - failed to send data to MongoDB
33 | Delete Button doesn't work
34 | Background images did not load as planned
35 | Forecast not showing as planned
36 | Basically 70% of the plan
--------------------------------------------------------------------------------
/src/utilities/plan-api.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | // // This is the base path of the Express route we'll define
4 | // const BASE_URL = 'http://localhost:3001/api/plan';
5 |
6 | // export function savingData(savedPlan) {
7 | // return sendRequest(BASE_URL, 'POST', savedPlan);
8 | // }
9 |
10 | // /*--- Helper Functions ---*/
11 |
12 | // async function sendRequest(url, method = 'GET', payload = null) {
13 | // // Fetch accepts an options object as the 2nd argument
14 | // // used to include a data payload, set headers, etc.
15 | // const options = { method };
16 | // if (payload) {
17 | // options.headers = { 'Content-Type': 'application/json' };
18 | // options.body = JSON.stringify(payload);
19 | // }
20 |
21 |
22 | // const res = await fetch(url, options);
23 | // // res.ok will be false if the status code set to 4xx in the controller action
24 | // if (res.ok) return res.json();
25 | // throw new Error('Bad Request');
26 | // }
27 |
--------------------------------------------------------------------------------
/models/user.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose")
2 | const bcrypt = require("bcrypt")
3 | const Schema = mongoose.Schema
4 | const SALT_ROUNDS = 6
5 |
6 | const userSchema = new Schema(
7 | {
8 | name: {
9 | type: String,
10 | required: true
11 | },
12 | email: {
13 | type: String,
14 | unique: true,
15 | trim: true,
16 | lowercase: true,
17 | required: true
18 | },
19 | password: {
20 | type: String,
21 | trim: true,
22 | minLength: 3,
23 | required: true
24 | },
25 | },
26 | {
27 | timestamps: true,
28 | toJSON: {
29 | transform: function(doc, ret){
30 | delete ret.password;
31 | return ret
32 | }
33 | }
34 |
35 | })
36 |
37 | userSchema.pre('save', async function(next){
38 | if (!this.isModified('password')) return next();
39 |
40 | this.password = await bcrypt.hash(this.password, SALT_ROUNDS)
41 | return next()
42 | })
43 |
44 |
45 | module.exports = mongoose.model('user', userSchema)
--------------------------------------------------------------------------------
/src/components/NavBar.js:
--------------------------------------------------------------------------------
1 | import { useState} from 'react'
2 | import { Link, NavLink } from "react-router-dom";
3 | import * as userService from '../utilities/users-service';
4 | import Itinerary from '../pages/Itinerary';
5 |
6 | const NavBar = ({user, setUser}) => {
7 |
8 | function handleLogOut() {
9 | // Delegate to the users-service
10 | userService.logOut();
11 | // Update state will also cause a re-render
12 | setUser(null);
13 | }
14 |
15 | return (
16 |
17 | Saved Itinerary *
18 | Itineraries
19 |
20 | Welcome, {user.name}!
21 |
22 |
23 | Log Out
24 |
25 | )
26 | }
27 |
28 | const myStyles = {
29 | welcome: {
30 | fontSize: '20px',
31 | color: 'white',
32 | fontWeight: 'bold'
33 | }
34 |
35 | }
36 | export default NavBar
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const morgan = require('morgan')
3 | const favicon = require('serve-favicon')
4 | const path = require('path')
5 | require('dotenv').config()
6 | // Connecting to database
7 | require ('./config/database')
8 | const cors = require("cors")
9 |
10 |
11 | const app = express()
12 | const PORT = process.env.PORT || 3001;
13 |
14 | // Plans
15 | // const plan = require('./routes/api/plan')
16 |
17 | // Middleware
18 | app.use(cors())
19 | app.use(morgan('dev'))
20 | app.use(express.json())
21 | // app.use(favicon(path.join(__dirname, 'build', 'favicon.ico')));
22 | app.use(express.static(path.join(__dirname, 'build')))
23 |
24 | // Middleware to verify token and assign user object of payload to req.user.
25 | // Be sure to mount before routes
26 | app.use(require('./config/checkToken'));
27 |
28 |
29 | // Routes
30 | app.use('/api/users', require('./routes/api/users'))
31 |
32 | // API Routes
33 | // app.get('/orders',(req, res) => {
34 | // })
35 | // app.get('/orders/new',(req, res) => {
36 | // })
37 |
38 | // Routes for the Saved Itinerary
39 | // app.use('/api/plan', require('./routes/api/plan'))
40 | // app.use('/api/plan', plan)
41 |
42 |
43 | // Catch All to serve the production app
44 | app.get('/*', (req, res) => {
45 | res.send(path.join(__dirname, 'build', 'index.html'))
46 | })
47 |
48 | app.listen(PORT, () =>{
49 | console.log(`Server running on port: ${PORT}`);
50 | })
51 |
52 |
--------------------------------------------------------------------------------
/controllers/api/users.js:
--------------------------------------------------------------------------------
1 | const User = require('../../models/user')
2 | const jwt = require('jsonwebtoken')
3 | const bcrypt = require('bcrypt')
4 |
5 |
6 | async function create(req, res) {
7 | try {
8 | console.log(req.body);
9 | // Add the user to the database
10 | const user = await User.create(req.body)
11 | console.log(user);
12 | // Create JWT Token
13 | const token = createJWT(user)
14 | // Send token to client
15 | res.json(token)
16 | } catch (error) {
17 | console.log(error);
18 | res.status(400).json(error)
19 | }
20 | }
21 |
22 | async function logIn(req, res) {
23 | try {
24 | const user = await User.findOne({email: req.body.email})
25 | const match = await bcrypt.compare(req.body.password, user.password)
26 | if(match){
27 | const token = createJWT(user)
28 | res.json(token)
29 | }
30 | } catch (error) {
31 | res.status(400).json('Bad Credentials');
32 | }
33 | }
34 |
35 | function checkToken(req, res) {
36 | // req.user will always be there for you when a token is sent
37 | console.log('req.user', req.user);
38 | res.json(req.exp);
39 | }
40 |
41 | // -------Helper Function ------
42 | function createJWT(user){
43 | return jwt.sign({user},process.env.SECRET, {expiresIn: '24h'}
44 | )
45 | }
46 |
47 | module.exports = {
48 | create,
49 | logIn,
50 | checkToken,
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "travelplanningapp",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "axios": "^1.1.3",
10 | "bcrypt": "^5.1.0",
11 | "bootstrap": "^5.2.2",
12 | "cors": "^2.8.5",
13 | "dotenv": "^16.0.3",
14 | "express": "^4.18.2",
15 | "jsonwebtoken": "^8.5.1",
16 | "mongoose": "^6.7.0",
17 | "morgan": "^1.10.0",
18 | "react": "^18.2.0",
19 | "react-background-slider": "^3.0.0-0",
20 | "react-bootstrap": "^2.6.0",
21 | "react-dom": "^18.2.0",
22 | "react-router-dom": "^6.4.2",
23 | "react-scripts": "5.0.1",
24 | "react-select-datepicker": "^2.1.2",
25 | "serve-favicon": "^2.5.0",
26 | "web-vitals": "^2.1.4"
27 | },
28 | "scripts": {
29 | "start": "react-scripts start",
30 | "build": "react-scripts build",
31 | "test": "react-scripts test",
32 | "eject": "react-scripts eject"
33 | },
34 | "eslintConfig": {
35 | "extends": [
36 | "react-app",
37 | "react-app/jest"
38 | ]
39 | },
40 | "browserslist": {
41 | "production": [
42 | ">0.2%",
43 | "not dead",
44 | "not op_mini all"
45 | ],
46 | "development": [
47 | "last 1 chrome version",
48 | "last 1 firefox version",
49 | "last 1 safari version"
50 | ]
51 | },
52 | "proxy": "http://localhost:3001"
53 | }
54 |
--------------------------------------------------------------------------------
/controllers/api/plan.js:
--------------------------------------------------------------------------------
1 | // const Plan = require('../../models/plan')
2 |
3 | // // Save Plan to the Database
4 |
5 | // async function savePlan(req, res) {
6 | // try {
7 | // // Save the plan to the database
8 | // const tripPlan = await new Plan.create({name: req.body.name, img: req.body.img, location: req.body.location, website: req.body.website})
9 | // // const saveTrip = await tripPlan.save()
10 |
11 | // res.status(200).send(saveTask);
12 | // } catch (error) {
13 | // res.status(400).json(error)
14 | // }
15 | // }
16 |
17 | // async function readPlan (req, res) {
18 | // try {
19 | // const allPlans = await Plan.find({})
20 | // res.status(200).json(allPlans)
21 | // } catch (error) {
22 | // res.status(400).json(err)
23 | // }
24 | // }
25 |
26 | // async function updatePlan (req, res) {
27 | // try {
28 | // const editPlan = await Plan.findByIdAndUpdate(req.params.id, req.body)
29 | // res.status(200).json(editPlan)
30 | // } catch (error) {
31 | // res.status(400).json(error)
32 |
33 | // }
34 | // }
35 |
36 | // async function deletePlan(req, res) {
37 | // try {
38 | // await Plan.findByIdAndDelete(reqq.params.id)
39 | // res.status(200).send('DELETED')
40 | // } catch (error) {
41 | // res.status(400).json(error)
42 | // }
43 | // }
44 |
45 |
46 | // module.exports = {
47 | // savePlan,
48 | // readPlan,
49 | // updatePlan,
50 | // deletePlan,
51 | // }
--------------------------------------------------------------------------------
/src/components/LogInForm.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import * as usersService from '../utilities/users-service';
3 | import '../../src/App.css'
4 |
5 | const LogInForm = ({ setUser }) => {
6 | const [credentials, setCredentials] = useState({
7 | email: '',
8 | password: ''
9 | });
10 | const [error, setError] = useState('');
11 |
12 | function handleChange(evt) {
13 | setCredentials({ ...credentials, [evt.target.name]: evt.target.value });
14 | setError('');
15 | }
16 |
17 | async function handleSubmit(evt) {
18 | // Prevent form from being submitted to the server
19 | evt.preventDefault();
20 | try {
21 | // The promise returned by the signUp service method
22 | // will resolve to the user object included in the
23 | // payload of the JSON Web Token (JWT)
24 | const user = await usersService.logIn(credentials);
25 | setUser(user);
26 | } catch {
27 | setError('Log In Failed - Try Again');
28 | }
29 | }
30 |
31 | return (
32 |
33 |
34 |
35 |
36 |
46 |
47 |
48 |
{error}
49 |
50 | );
51 | }
52 | export default LogInForm
--------------------------------------------------------------------------------
/src/components/Weather.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react'
2 | import Forecast from './Forecast'
3 | import Dropdown from 'react-bootstrap/Dropdown';
4 | import DropdownButton from 'react-bootstrap/DropdownButton';
5 | import '../../src/App.css'
6 |
7 |
8 | const Weather = () => {
9 |
10 | // state to hold the weather data
11 | const [weather, setWeather] = useState('')
12 |
13 | useEffect(() => {
14 | // console.log(weather)
15 | }, [weather]);
16 |
17 | const url = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Coron%2C%20Palawan%2C%20Philippines/next5days?iconSet=icons1&unitGroup=metric&elements=datetime%2Cname%2Ctempmax%2Ctempmin%2Ctemp%2Ccloudcover%2Cconditions&key=MD3V4ER9SPR7GCLY5LBS4Z33Z&contentType=json"
18 |
19 | // Function to fetch weather data
20 | const getWeather = async () => {
21 | try {
22 | const res = await fetch(url)
23 | const data = await res.json()
24 | console.log(data);
25 |
26 | setWeather(data)
27 |
28 | } catch (error) {
29 | console.log(error);
30 | }
31 | }
32 |
33 |
34 |
35 |
36 | return (
37 |
38 |
39 |
Get 8-Day Forecast
40 |
41 | {weather && weather.days.map((i, index) => (
42 |
54 | ))}
55 |
56 |
57 |
58 |
59 | )}
60 |
61 |
62 |
63 |
64 |
65 | export default Weather
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/utilities/users-service.js:
--------------------------------------------------------------------------------
1 |
2 | import * as usersAPI from './users-api'
3 |
4 | export async function signUp(userData) {
5 | // Delegate the network request code to the users-api.js API module
6 | // which will ultimately return a JSON Web Token (JWT)
7 | const token = await usersAPI.signUp(userData);
8 |
9 | // Baby step by returning whatever is sent back by the server
10 | // return token;
11 |
12 | localStorage.setItem('token', token)
13 | return getUser()
14 | }
15 |
16 | // ======= LOG IN =========
17 |
18 | export async function logIn(credentials) {
19 | // Delegate the network request code to the users-api.js API module
20 | // which will ultimately return a JSON Web Token (JWT)
21 | const token = await usersAPI.logIn(credentials);
22 |
23 | // Baby step by returning whatever is sent back by the server
24 | // return token;
25 |
26 | localStorage.setItem('token', token)
27 | return getUser()
28 | }
29 |
30 | export async function checkToken(){
31 | // Just so that you don't forget how to use .then
32 | return usersAPI.checkToken()
33 | // checkToken returns a string, but let's
34 | // make it a Date object for more flexibility
35 | .then(dateStr => new Date(dateStr));
36 | }
37 |
38 | export function getToken(){
39 | // get token from local storage
40 | const token = localStorage.getItem('token')
41 | if (!token) return null;
42 |
43 | // if we have a token
44 | const payload = JSON.parse(atob(token.split('.')[1]))
45 | console.log(payload);
46 |
47 | if (payload.exp < Date.now() / 1000){
48 | localStorage.removeItem('token')
49 | return null
50 | }
51 | return token;
52 | }
53 |
54 | export function getUser(){
55 | const token = getToken()
56 | return token ? JSON.parse(atob(token.split('.')[1])).user : null;
57 | }
58 |
59 | export function logOut() {
60 | localStorage.removeItem('token');
61 | }
--------------------------------------------------------------------------------
/src/components/picsforapp.js:
--------------------------------------------------------------------------------
1 | const locationDetails = [
2 | {
3 | name: "How to get to Palawan",
4 | img: "https://nrdc.denr.gov.ph/wp-content/uploads/2021/11/suggested-itinerary-palawan-philippines.jpg"
5 | },
6 | {
7 | name: "Puerto Princesa",
8 | img: "https://a.cdn-hotels.com/gdcs/production197/d112/49a455b8-8359-435d-822b-5617701c984e.jpg",
9 | youtube: "https://www.youtube.com/watch?v=oykUbTHdqto"
10 | },
11 | ]
12 |
13 | const funPics = [
14 | {
15 | name: "Puerto Princesa 1",
16 | img: "https://uploads.mwp.mprod.getusinfo.com/uploads/sites/24/2022/10/10-04-2022-PR-USAID-Gives-Awards-to-Four-Outstanding-Marine-Protected-Areas-in-Palawan-resized-2.png"
17 | },
18 | {
19 | name: "El Nido 1",
20 | img: "https://a.cdn-hotels.com/gdcs/production129/d1719/eaa3ce8a-cb82-4e0c-9b8a-1dda760d14d2.jpg?impolicy=fcrop&w=800&h=533&q=medium.jpg"
21 | },
22 | {
23 | name: "Coron 1",
24 | img: "https://www.journeyera.com/wp-content/uploads/2016/11/what-to-do-in-coron-04908.jpg"
25 | },
26 | {
27 | name: "Coron 2",
28 | img: "https://media.tacdn.com/media/attractions-splice-spp-674x446/07/11/b7/a0.jpg"
29 | },
30 | {
31 | name: "El Nido 2",
32 | img: "https://elnido-hotels.com/wp-content/uploads/2019/05/activities.jpg"
33 | },
34 | {
35 | name: "Beach View",
36 | img: "https://www.beautifulworld.com/wp-content/uploads/2016/10/PALAWAN-ISLAND.jpg"
37 | },
38 | {
39 | name: "Beach View 2",
40 | img: "https://i0.wp.com/thetravellingfeet.com/wp-content/uploads/2020/10/palawan-best-island-in-the-philippines.jpg?fit=1070%2C647&ssl=1.jpg"
41 | },
42 | {
43 | name: "Sea shore",
44 | img: "https://i0.wp.com/www.tikigo.com/wp-content/uploads/linapacan-island-palawan.jpg?resize=800%2C534&ssl=1.jpg"
45 | },
46 | {
47 | name: "",
48 | img: "https://www.travel-palawan.com/wp-content/uploads/2018/03/beach-1.jpg"
49 | }
50 |
51 | ]
52 |
53 | module.exports = funPics
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | font-family: sans-serif;
4 | background-color:rgb(59, 139, 163);
5 | background-position-x: center;
6 | /* background-size: cover ; */
7 | /* background-image: url("https://windows10spotlight.com/wp-content/uploads/2020/09/0ef88fa434c849a3472ec0af13970f6f.jpg") no-repeat; */
8 | }
9 | .main {
10 |
11 | height: 100%;
12 | width: 100%;
13 | position: absolute;
14 | top: 0;
15 | }
16 |
17 | .popup{
18 | height: 260px;
19 | border-width: 10rem;
20 | text-align: justify;
21 | position: absolute;
22 | top: 25%;
23 | right: 25%;
24 | background-color: rgb(129, 206, 209);
25 | }
26 |
27 | .weather{
28 | font-size: 15px;
29 | color: rgb(214, 233, 236);
30 | display: flex;
31 | flex-direction: row;
32 | background-color: rgb(18, 112, 141);
33 | flex-wrap: wrap;
34 | }
35 |
36 | .form-container {
37 | display: flex;
38 | flex-direction: column;
39 | background-color: rgb(170, 237, 239);
40 |
41 | }
42 |
43 | form{
44 | background-color: rgb(133, 213, 214);
45 | margin: 10px;
46 | /* font-display: block; */
47 | box-shadow: 20px 20px 50px rgb(94, 223, 216),
48 | -30px -30px 60px #248ba4;
49 | }
50 |
51 | input{
52 | align-content: center;
53 |
54 | }
55 | /*
56 | .slideshow {
57 | margin: 0 auto;
58 | overflow: hidden;
59 | max-width: 500px;
60 | }
61 |
62 | /* Slideshow */
63 | /*
64 | .slideshow {
65 | margin: 0 auto;
66 | overflow: hidden;
67 | max-width: 500px;
68 | }
69 |
70 | .slideshowSlider {
71 | white-space: nowrap;
72 | transition: ease 1000ms;
73 | }
74 |
75 | .slide {
76 | display: inline-block;
77 |
78 | height: 400px;
79 | width: 100%;
80 | border-radius: 40px;
81 | }
82 |
83 | /* Buttons */
84 | /*
85 | .slideshowDots {
86 | text-align: center;
87 | }
88 |
89 | .slideshowDot {
90 | display: inline-block;
91 | height: 20px;
92 | width: 20px;
93 | border-radius: 50%;
94 |
95 | cursor: pointer;
96 | margin: 15px 7px 0px;
97 |
98 | background-color: #c4c4c4;
99 | }
100 |
101 | .slideshowDot.active {
102 | background-color: #6a0dad;
103 | } */
--------------------------------------------------------------------------------
/src/utilities/users-api.js:
--------------------------------------------------------------------------------
1 |
2 | import { getToken } from './users-service';
3 |
4 | // This is the base path of the Express route we'll define
5 | const BASE_URL = '/api/users';
6 |
7 | export function signUp(userData) {
8 | return sendRequest(BASE_URL, 'POST', userData);
9 | }
10 |
11 | export function logIn(credentials) {
12 | return sendRequest(`${BASE_URL}/login`, 'POST', credentials);
13 | }
14 |
15 | /*--- Helper Functions ---*/
16 |
17 | async function sendRequest(url, method = 'GET', payload = null) {
18 | // Fetch accepts an options object as the 2nd argument
19 | // used to include a data payload, set headers, etc.
20 | const options = { method };
21 | if (payload) {
22 | options.headers = { 'Content-Type': 'application/json' };
23 | options.body = JSON.stringify(payload);
24 | }
25 |
26 | const token = getToken();
27 | if (token) {
28 | // Ensure the headers object exists
29 | options.headers = options.headers || {};
30 | // Add token to an Authorization header
31 | // Prefacing with 'Bearer' is recommended in the HTTP specification
32 | options.headers.Authorization = `Bearer ${token}`;
33 | }
34 |
35 | const res = await fetch(url, options);
36 | // res.ok will be false if the status code set to 4xx in the controller action
37 | if (res.ok) return res.json();
38 | throw new Error('Bad Request');
39 | }
40 |
41 | export async function checkToken(){
42 | return sendRequest(`${BASE_URL}/check-token`);
43 | }
44 |
45 | // export const signUp = async(userData) => {
46 | // const res = await fetch(BASE_URL, {
47 | // method: 'POST',
48 | // headers: {'Content-Type': 'application/json'},
49 | // body: JSON.stringify(userData)
50 | // })
51 |
52 | // if (res.ok){
53 | // return res.json()
54 |
55 | // }else {
56 | // throw new Error('Invalid Sign Up')
57 | // }
58 | // }
59 |
60 | // // =====LOG IN=======
61 |
62 | // export const logIn = async(userData) => {
63 | // const res = await fetch(BASE_URL + '/login', {
64 | // method: 'POST',
65 | // headers: {'Content-Type': 'application/json'},
66 | // body: JSON.stringify(userData)
67 | // })
68 |
69 | // if (res.ok){
70 | // return res.json()
71 |
72 | // }else {
73 | // throw new Error('Invalid Log In')
74 | // }
75 | // }
76 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/BackgroundSlider.js:
--------------------------------------------------------------------------------
1 | // import React from "react";
2 | // import '../../src/App.css'
3 |
4 | // const funPics = [
5 | // "https://uploads.mwp.mprod.getusinfo.com/uploads/sites/24/2022/10/10-04-2022-PR-USAID-Gives-Awards-to-Four-Outstanding-Marine-Protected-Areas-in-Palawan-resized-2.png",
6 | // "https://a.cdn-hotels.com/gdcs/production129/d1719/eaa3ce8a-cb82-4e0c-9b8a-1dda760d14d2.jpg?impolicy=fcrop&w=800&h=533&q=medium.jpg",
7 | // "https://www.journeyera.com/wp-content/uploads/2016/11/what-to-do-in-coron-04908.jpg",
8 | // "https://media.tacdn.com/media/attractions-splice-spp-674x446/07/11/b7/a0.jpg",
9 | // "https://elnido-hotels.com/wp-content/uploads/2019/05/activities.jpg",
10 | // "https://www.beautifulworld.com/wp-content/uploads/2016/10/PALAWAN-ISLAND.jpg",
11 | // "https://i0.wp.com/thetravellingfeet.com/wp-content/uploads/2020/10/palawan-best-island-in-the-philippines.jpg?fit=1070%2C647&ssl=1.jpg",
12 | // "https://i0.wp.com/www.tikigo.com/wp-content/uploads/linapacan-island-palawan.jpg?resize=800%2C534&ssl=1.jpg",
13 | // "https://www.travel-palawan.com/wp-content/uploads/2018/03/beach-1.jpg" ]
14 | // const delay = 2500;
15 |
16 | // function BackgroundSlider() {
17 | // const [index, setIndex] = React.useState(0);
18 | // const timeoutRef = React.useRef(null);
19 |
20 | // function resetTimeout() {
21 | // if (timeoutRef.current) {
22 | // clearTimeout(timeoutRef.current);
23 | // }
24 | // }
25 |
26 | // React.useEffect(() => {
27 | // resetTimeout();
28 | // timeoutRef.current = setTimeout(
29 | // () =>
30 | // setIndex((prevIndex) =>
31 | // prevIndex === funPics.length - 1 ? 0 : prevIndex + 1
32 | // ),
33 | // delay
34 | // );
35 |
36 | // return () => {
37 | // resetTimeout();
38 | // };
39 | // }, [index]);
40 |
41 | // return (
42 | //
43 | //
47 | // {funPics.map((img, index) => (
48 | //
53 | // ))}
54 | //
55 |
56 | //
57 | // {funPics.map((_, idx) => (
58 | //
{
62 | // setIndex(idx);
63 | // }}
64 | // >
65 | // ))}
66 | //
67 | //
68 | // );
69 | // }
70 |
71 | // export default BackgroundSlider
72 |
--------------------------------------------------------------------------------
/src/pages/SavedItineraries.js:
--------------------------------------------------------------------------------
1 | import { checkToken } from "../utilities/users-service"
2 | import Button from 'react-bootstrap/Button';
3 | import Card from 'react-bootstrap/Card';
4 | import Container from 'react-bootstrap/Container'
5 | import { placesToVisit, activities, placesToEat, accommodation } from "../components/data";
6 | import Itinerary from "./Itinerary";
7 | import { useState } from 'react'
8 | // import planSchema from "../../models/plan"
9 | // import { savingData } from '../utilities/plan-service'
10 | // import axios from 'axios'
11 |
12 |
13 | const SavedItineraries = (props) => {
14 | const { savedItinerary } = props
15 |
16 |
17 |
18 | // const state ={
19 | // name: '',
20 | // img: '',
21 | // location:'',
22 | // website:'',
23 | // error:'',
24 | // }
25 |
26 | const handleCheckToken = async () => {
27 | const expDate = await checkToken()
28 | console.log(expDate);
29 | }
30 |
31 |
32 |
33 | return (
34 |
35 | Saved Itineraries
36 |
37 | Day 1
38 |
39 |
40 |
41 |
42 | Itinerary
43 |
44 |
45 |
46 |
47 | {savedItinerary && savedItinerary.map((item, index) => (
48 |
49 |
50 |
51 |
52 |
{item.name}
53 |
54 |
{item.location}
55 |
56 |
Website:
57 |
58 | Save
59 | Delete
60 |
61 |
62 | ))}
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Check When My Login Expires
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 |
82 |
83 | export default SavedItineraries
84 |
85 |
--------------------------------------------------------------------------------
/src/components/SignUpForm.js:
--------------------------------------------------------------------------------
1 | import { useState} from 'react'
2 | import { Component } from 'react';
3 | import { signUp } from '../utilities/users-service';
4 | import '../../src/App.css'
5 |
6 | //? SignUpForm.jsx <--> users-service.js <--> users-api.js <-Internet-> server.js (Express)
7 |
8 |
9 | export default class SignUpForm extends Component {
10 |
11 | state = {
12 | name: '',
13 | email: '',
14 | password: '',
15 | confirm: '',
16 | error: '',
17 | };
18 |
19 | handleChange = (evt) => {
20 | this.setState({ [evt.target.name]: evt.target.value, error: ""})
21 | }
22 |
23 | handleSubmit = async (e) => {
24 | e.preventDefault();
25 | // alert(JSON.stringify(this.state))
26 | try {
27 | const { name, email, password} = this.state;
28 | const formData = {name, email, password
29 | };
30 |
31 | // pass the formData to the Signup
32 | const user = await signUp(formData)
33 | this.props.setUser(user);
34 | // console.log(setUser);
35 | } catch {
36 | // if we have an error
37 | this.setState({error: "Sign up Failed - Try Again"})
38 | }
39 | }
40 |
41 | render() {
42 | const disable = this.state.password !== this.state.confirm;
43 | return (
44 |
45 |
46 |
86 |
87 |
{this.state.error}
88 |
89 | );
90 | }
91 |
92 |
93 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import '../src/App.css';
2 | import { useState } from 'react'
3 | import AuthPage from './pages/AuthPage'
4 | import Itinerary from './pages/Itinerary'
5 | import SavedItineraries from './pages/SavedItineraries'
6 | import NavBar from './components/NavBar'
7 | import { Routes, Route } from 'react-router-dom'
8 | import { getUser } from "./utilities/users-service"
9 | import Weather from './components/Weather';
10 |
11 |
12 |
13 |
14 | function App() {
15 | const [user, setUser] = useState(getUser())
16 | const [savedItinerary, setSavedItinerary] = useState([])
17 |
18 | // const [savedPlan, setSavedPlan] = useState([])
19 |
20 | const [popUp, setPopUp] = useState(false)
21 |
22 |
23 | const handleClickOpen = () => {
24 | setPopUp(!popUp)
25 | }
26 | const closePopUp = () => {
27 | setPopUp(false)
28 | }
29 |
30 | return (
31 |
32 |
33 |
37 |
38 |
39 |
40 | {
41 | user ? (
42 |
43 |
44 |
45 | } />
46 | } />
47 |
48 |
49 | ) : (
50 | (popUp ?
51 |
52 |
53 |
x
54 |
55 |
56 |
57 |
58 |
:'')
59 | )}
60 |
61 |
62 | {'\t'}The paradisal province of Palawan is a constant feature in many international “Best In The World” lists, thanks to its rich and diverse flora and fauna, and much-preserved natural attractions. Discover why healthy ecotourism is such an essential part in maintaining the natural wonders of this heaven on earth.
63 |
64 |
65 | {'\t'}
66 | To say Palawan is a beach bum's fantasy is an understatement. Sailing the length of the province from the north to the southern tip of the main island-brings you up close and personal with paradise in countless forms: from the coral-fringed dreamscapes of the Calamianes and the karst limestone formations of El Nido, to the wind-swept shorelines of central Palawan and the pristine sandbars of Balabac.
67 |
68 |
69 | Quite simply, Palawan has the best beaches—not only in the Philippines, but in all of southeast Asia. The best part? Only a fraction of them are known.
70 |
71 |
72 | Palawan has always had an environmental streak. It was one of the first provinces to crack down on litter, noise pollution, and single-use plastics. A lot is at stake, as the province's booming tourism industry relies on the successful preservation of its pristine ecology and natural beauty. Against this backdrop, several award winning resorts are leading the way toward a more sustainable future, blending native design and low carbon elements like solar panels, composting, and edible gardens to create living spaces that will last.
73 |
74 | {/* */}
75 |
76 | {/* */}
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | );
89 | }
90 |
91 |
92 |
93 | export default App;
94 |
--------------------------------------------------------------------------------
/src/pages/Itinerary.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { placesToVisit, activities, placesToEat, accommodation } from "../components/data"
3 | import Button from 'react-bootstrap/Button';
4 | import Card from 'react-bootstrap/Card';
5 | // import { SelectDatepicker } from 'react-select-datepicker';
6 |
7 | const Itinerary = (props) => {
8 | const {savedItinerary, setSavedItinerary} = props
9 |
10 | return (
11 |
12 |
13 |
Itinerary
14 |
15 |
16 |
17 |
Places to Visit
18 |
19 | {placesToVisit.map((place, index) => (
20 |
21 |
22 |
23 |
24 | {place.name}
25 |
26 | Description
27 |
28 | setSavedItinerary([...savedItinerary, place])} variant="success">Add to itinerary
29 |
30 |
31 |
32 | ))}
33 |
34 |
35 |
36 |
37 |
38 |
Activities
39 |
40 | {activities.map((activities, index) => (
41 |
42 |
43 |
44 |
45 | {activities.name}
46 |
47 | {activities.location}
48 |
49 | Visit the Website
50 |
51 | setSavedItinerary([...savedItinerary, activities])} variant="success">Add to itinerary
52 |
53 |
54 |
55 | ))}
56 |
57 |
58 |
59 |
60 |
61 |
Places to Eat
62 |
63 | {placesToEat.map((food, index) => (
64 |
65 |
66 |
67 |
68 | {food.name}
69 |
70 | {food.location}
71 |
72 | Visit the Website
73 |
74 | setSavedItinerary([...savedItinerary, food])} variant="success">Add to itinerary
75 |
76 |
77 |
78 | ))}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
Places to Stay
86 |
87 | {accommodation.map((stay, index) => (
88 |
89 |
90 |
91 |
92 | {stay.name}
93 |
94 | {stay.location}
95 |
96 | Visit the Website
97 |
98 | setSavedItinerary([...savedItinerary, stay])} variant="success">Add to itinerary
99 |
100 |
101 |
102 | ))}
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | )
111 | }
112 | export default Itinerary
--------------------------------------------------------------------------------
/src/components/data.js:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom"
2 |
3 | export const placesToVisit = [{
4 | name: 'Kayangan Lake',
5 | img: "https://gttp.imgix.net/225409/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-4.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg"
6 | },
7 | {
8 | name: 'Barracuda Lake',
9 | img: "https://gttp.imgix.net/225414/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-5.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg"
10 | },
11 | {
12 | name: 'Siete Pecados',
13 | img: "https://gttp.imgix.net/225415/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-6.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
14 | },
15 | {
16 | name: 'Malcapuya Island',
17 | img: "https://gttp.imgix.net/225416/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-7.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
18 | },
19 | {
20 | name: 'Twin Lagoon',
21 | img:"https://gttp.imgix.net/225417/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-8.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
22 | },
23 | {
24 | name: 'Maquinit Hot Spring',
25 | img: "https://sweetescapeholiday.ph/wp-content/uploads/2020/07/Maniquit-Hot-Spring.jpg",
26 | },
27 | {
28 | name: 'Culion Island',
29 | img: "https://mediaim.expedia.com/localexpert/1076367/7ff9f679-f8e8-4924-a6fc-5833c4e13c19.jpg?impolicy=resizecrop&rw=1005&rh=565.jpg",
30 | },
31 | {
32 | name: 'Busuanga Island (Malajon Island to the locals)',
33 | img: "https://waytogo.s3.ap-southeast-1.amazonaws.com/wp-content/uploads/2015/11/09172402/Busuanga-2.jpg",
34 | },
35 | {
36 | name: 'Calauit Safari Park',
37 | img: "https://gttp.imgix.net/225424/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-12.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
38 | },
39 | {
40 | name: 'Banana Island',
41 | img: "https://www.shoreexcursions.asia/wp-content/uploads/2019/11/Banana-Island-Coron-Shore-Excursion.jpg",
42 | },
43 | {
44 | name: 'Pass Island',
45 | img: "https://gttp.imgix.net/225426/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-13.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
46 | },
47 | {
48 | name: 'Coron Youth Club Beach',
49 | img: "https://gttp.imgix.net/225429/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-14.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
50 | },
51 | {
52 | name: 'Bulog Dos Island',
53 | img: "https://gttp.imgix.net/225427/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-16.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
54 |
55 | },
56 | {
57 | name: 'Banul Beach',
58 | img: "https://gttp.imgix.net/225430/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-17.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
59 | }
60 | ]
61 |
62 | export const activities = [
63 | {
64 | name: 'Wreck Diving',
65 | img: "https://gttp.imgix.net/225419/x/0/top-18-things-to-do-in-coron-palawan-kayangan-lake-and-islands-15.jpg?auto=compress%2Cformat&ch=Width%2CDPR&dpr=1&ixlib=php-3.3.0&w=883.jpg",
66 | location: 'Coron Bay',
67 | website: "https://piratediverscoron.com/index.html"
68 | },
69 | {
70 | name: 'Parasailing, Jetski, Water Rides',
71 | img: "https://mediaim.expedia.com/localexpert/1284009/d9ce9e8f-a278-4807-9443-f3302f47730d.jpg?impolicy=resizecrop&rw=1005&rh=565.jpg",
72 | location: 'Coron Island',
73 | website: "https://www.royalislandwatersports.com/"
74 | },
75 | {
76 | name: 'Underground River Tour, Yacht and Camping',
77 | img: "https://static.wixstatic.com/media/43ce38_d9d9a0c56e7740a1978a6c9f17a3d3b9~mv2.jpg/v1/fill/w_1600,h_1071,al_c/43ce38_d9d9a0c56e7740a1978a6c9f17a3d3b9~mv2.jpg",
78 | location: 'Puerto Princesa Subterranean River National Park',
79 | website: "https://www.elnidoadventure.com/"
80 | },
81 | {
82 | name: 'Scuba Diving and Snorkeling',
83 | img: "https://www.andbeyond.com/wp-content/uploads/sites/5/phinda-scuba-fishes.jpg",
84 | location: 'El Nido',
85 | website: 'https://www.palawan-divers.org/padi-discover-scuba-diving-el-nido/'
86 | },
87 | {
88 | name: 'Zipline Adventure',
89 | img: "https://livingnomads.com/wp-content/uploads/2017/12/30/zipline-adventure.jpg",
90 | location: 'Puerto Princesa',
91 | website: "https://www.facebook.com/sabangxzipline/"
92 | },
93 | {
94 | name: 'Island Hopping',
95 | img: "https://cdn.getyourguide.com/img/tour/5c7755427d7f7.jpeg/99.jpg",
96 | location: 'All Over Palawan',
97 | website: 'https://www.elnidoparadise.com/island-hopping/el-nido-tours/'
98 | }
99 | ]
100 |
101 | export const placesToEat = [
102 | {
103 | name: "Artcafe",
104 | img: "http://elnidoboutiqueandartcafe.com/wp-content/uploads/2018/11/20200827_181722-01-800x600.jpg",
105 | location: 'El Nido',
106 | website: 'http://elnidoboutiqueandartcafe.com/'
107 | },
108 | {
109 | name: "Big Bad Thai Bistro and Bar",
110 | img: "https://media-cdn.tripadvisor.com/media/photo-s/19/87/33/4a/20191008-153430-largejpg.jpg",
111 | location: 'El Nido',
112 | website: "https://www.facebook.com/bigbadthai/"
113 | },
114 | {
115 | name: "Badjao Seafront Restaurant",
116 | img: "https://livingnomads.com/wp-content/uploads/2018/03/05/Badjao-Crab.jpg",
117 | location:'Puerto Princesa',
118 | website: 'https://www.facebook.com/badjaoseafrontrestaurant/'
119 | },
120 | {
121 | name: "Kalui",
122 | img: "https://www.purefoodtravel.com/wp-content/uploads/2014/03/kalui_restaurant_2.jpg",
123 | location: "Puerto Princesa",
124 | website: "https://www.facebook.com/people/Kalui-Restaurant/100067595345168/"
125 | }
126 | ]
127 |
128 | export const accommodation = [
129 | {
130 | name: "El Nido Resorts",
131 | img: "https://www.ayalaland.com.ph/app/uploads/2020/10/Picture1a.jpg",
132 | location: "In 4 Locations: Apulit Island, Miniloc Island, Lagen Island and Pangulasian Island",
133 | website: 'https://www.elnidoresorts.com/'
134 | },
135 | {
136 | name: "Club Paradise Palawan",
137 | img: "https://justglobetrotting.com/wp-content/uploads/2017/06/club-paradise-palawan.jpg",
138 | location: "Coron, Northern Palawan",
139 | website: 'https://www.clubparadisepalawan.com/'
140 | },
141 | {
142 | name: "El Rio Y Mar Resort",
143 | img: "https://i.travelapi.com/hotels/5000000/4160000/4155100/4155083/928a62b3_z.jpg",
144 | location: "Busuanga, Palawan",
145 | website: "https://cocovanabeachresort.business.site/"
146 | },
147 | {
148 | name: "Cauayan Island Resort",
149 | img: "https://images.trvl-media.com/hotels/13000000/12700000/12696900/12696876/c0d01461_z.jpg",
150 | location: "El Nido",
151 | website: "https://cauayanresort.com/"
152 | }
153 | ]
154 |
155 |
--------------------------------------------------------------------------------