├── 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 | 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 | 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 |
37 |      38 | 39 |
40 |      41 | 42 |   
43 |
44 | 45 |
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 | 40 | 41 | {weather && weather.days.map((i, index) => ( 42 |
43 |
44 | 45 | 52 | 53 |
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 | 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 | 59 |
60 |
61 |
62 | ))} 63 |
64 |
65 |
66 | 67 |
68 | 69 |
70 | 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 |
47 | 48 |    49 | 55 |
56 |    57 | 63 |
64 |    65 | 71 |
72 |    73 | 79 |
80 | 85 |
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 | 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 | 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 | 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 | 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 | --------------------------------------------------------------------------------