├── README.md
├── .gitignore
├── src
├── static
│ ├── cats.jpg
│ ├── cats2.jpg
│ ├── cats3.jpg
│ ├── js
│ │ ├── pages
│ │ │ ├── view.js
│ │ │ ├── About.js
│ │ │ ├── Contact.js
│ │ │ └── Home.js
│ │ └── index.js
│ └── css
│ │ └── styles.css
└── index.html
├── package.json
└── server.js
/README.md:
--------------------------------------------------------------------------------
1 | # single-page-application-LogRocket
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | node_modules/.bin/
3 |
4 | node_modules/
5 |
--------------------------------------------------------------------------------
/src/static/cats.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Njong392/single-page-application-LogRocket/HEAD/src/static/cats.jpg
--------------------------------------------------------------------------------
/src/static/cats2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Njong392/single-page-application-LogRocket/HEAD/src/static/cats2.jpg
--------------------------------------------------------------------------------
/src/static/cats3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Njong392/single-page-application-LogRocket/HEAD/src/static/cats3.jpg
--------------------------------------------------------------------------------
/src/static/js/pages/view.js:
--------------------------------------------------------------------------------
1 | export default class{
2 | constructor(){
3 |
4 | }
5 |
6 | setTitle(title){
7 | document.title = title;
8 | }
9 |
10 | async getHtml(){
11 | return '';
12 | }
13 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spa-logrocket",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "express": "^4.18.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const path = require('path');
3 | const hostname = '127.0.0.1';
4 | const port = 3001;
5 |
6 | const app = express();
7 |
8 | app.use("/static", express.static(path.resolve(__dirname,'src', 'static')));
9 |
10 | app.get("/*", (req, res) => {
11 | res.sendFile(path.resolve(__dirname, 'src', 'index.html'));
12 | });
13 |
14 | //listen for request on port 3000, and as a callback function have the port listened on logged
15 | app.listen(port, hostname, () => {
16 | console.log(`Server running at http://${hostname}:${port}/`);
17 | });
18 |
--------------------------------------------------------------------------------
/src/static/js/pages/About.js:
--------------------------------------------------------------------------------
1 | import view from './view.js'
2 |
3 | export default class extends view{
4 | constructor(){
5 | super();
6 | this.setTitle("About");
7 | }
8 |
9 | async getHtml(){
10 | return `
11 |
12 |
13 |
What we do at Meowie
14 |
Meowies lets you upload pictures of your cats, so that you never lose them. Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur commodi eveniet fugit veritatis. Id temporibus explicabo enim sunt, officiis sapiente.
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | `;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/static/js/pages/Contact.js:
--------------------------------------------------------------------------------
1 | import view from './view.js'
2 |
3 | export default class extends view{
4 | constructor(){
5 | super();
6 | this.setTitle("Contact us");
7 | }
8 |
9 | async getHtml(){
10 | return `
11 |
12 |
13 |
14 |
Get to us to make a custom album for your cat
15 |
Meowies lets you upload pictures of your cats, so that you never lose them. Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur commodi eveniet fugit veritatis. Id temporibus explicabo enim sunt, officiis sapiente.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | `;
27 | }
28 | }
--------------------------------------------------------------------------------
/src/static/js/pages/Home.js:
--------------------------------------------------------------------------------
1 | import view from './view.js'
2 |
3 | export default class extends view{
4 | constructor(){
5 | super();
6 | this.setTitle("Home");
7 | }
8 |
9 | async getHtml(){
10 | return `
11 |
12 |
13 |
An album for your cuties
14 |
Meowies lets you upload pictures of your cats, so that you never lose them. Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur commodi eveniet fugit veritatis. Id temporibus explicabo enim sunt, officiis sapiente.
15 | Read about us here
16 |
17 |
18 |
19 |
20 |
21 |
22 | `;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Single Page App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/static/css/styles.css:
--------------------------------------------------------------------------------
1 | *{
2 | padding: 0;
3 | margin: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | .navbar{
8 | background-color: pink;
9 | padding: 20px;
10 | display: flex;
11 | justify-content: space-between;
12 | align-items: center;
13 | }
14 | .nav-items{
15 | display: flex;
16 | }
17 |
18 |
19 | a{
20 | text-decoration: none;
21 | color: white;
22 | font-weight: bold;
23 | font-size: x-large;
24 | }
25 | .link{
26 | color: pink;
27 | font-size: medium;
28 | }
29 | .logo{
30 | color: white;
31 | font-weight: bold;
32 | font-size: xx-large;
33 | font-style: oblique;
34 | }
35 | ul{
36 | list-style: none;
37 | }
38 | .navbar ul li{
39 | margin-left: 15px;
40 | }
41 |
42 | #home{
43 | display: flex;
44 | align-items: center;
45 | margin: 20px;
46 | transform: translateY(100%);
47 |
48 | }
49 |
50 | .img{
51 | width: 80%;
52 | height: 80%;
53 | }
54 |
55 | .slider{
56 | position:fixed;
57 | top:0;
58 | left: 0;
59 | background-color: palevioletred;
60 | width: 100%;
61 | height: 100%;
62 | transform: translateY(100%);
63 | }
64 |
65 |
66 |
--------------------------------------------------------------------------------
/src/static/js/index.js:
--------------------------------------------------------------------------------
1 | import Home from './pages/Home.js'
2 | import About from './pages/About.js'
3 | import Contact from './pages/Contact.js'
4 |
5 | const tl = gsap.timeline({ defaults: {ease:'power2.out'} });
6 | tl.to('.slider', {y: "-100%", duration:1.2});
7 | tl.to('#home', {y: "0%", duration:1.2}, "-=1");
8 |
9 |
10 |
11 | const navigateTo = url => {
12 | history.pushState(null, null, url);
13 | router();
14 | };
15 |
16 | const router = async () => {
17 | const routes = [
18 | {
19 | path: "/",
20 | view: Home
21 | },
22 |
23 | {
24 | path: "/about",
25 | view: About
26 | },
27 |
28 | {
29 | path: "/contact",
30 | view: Contact
31 | }
32 |
33 |
34 | ];
35 |
36 | //test each route for match
37 | const checkMatches = routes.map(route => {
38 | return{
39 | route: route,
40 | isMatch: location.pathname === route.path //returns a boolean value
41 | };
42 | });
43 |
44 | let match = checkMatches.find(checkMatch => checkMatch.isMatch);
45 |
46 | if(!match){
47 | match = {
48 | route: routes[0],
49 | };
50 | }
51 |
52 | const view = new match.route.view();
53 |
54 | document.querySelector("#home").innerHTML = await view.getHtml();
55 |
56 |
57 | };
58 |
59 | window.addEventListener('popstate', router);
60 |
61 |
62 |
63 | document.addEventListener('DOMContentLoaded', () => {
64 |
65 | document.body.addEventListener('click', e => {
66 | e.preventDefault();
67 | tl.to('.slider', {y: "100%", duration:0});
68 |
69 |
70 | if(e.target.matches('[data-link]')){
71 |
72 | tl.to('.slider', {y: "-100%", duration:1.2});
73 | tl.fromTo('#home', {opacity: 0}, {opacity:1, duration:0.5});
74 | navigateTo(e.target.href);
75 |
76 | }
77 |
78 |
79 |
80 | })
81 |
82 |
83 | router();
84 | })
--------------------------------------------------------------------------------