Skip to content

Commit

Permalink
XPower UI: /home page
Browse files Browse the repository at this point in the history
  • Loading branch information
Kârūn The Rich committed May 23, 2024
1 parent c878342 commit cf353f6
Show file tree
Hide file tree
Showing 22 changed files with 275 additions and 42 deletions.
8 changes: 5 additions & 3 deletions app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import dotenv from 'dotenv';
dotenv.config();

// import routes
import spa from './routes/spa';
import error from './routes/error';
import home from './routes/home';
import ipfs from './routes/ipfs';
import migrate from './routes/migrate';
import nfts from './routes/nfts';
import ppts from './routes/ppts';
import ipfs from './routes/ipfs';
import robots from './routes/robots';
import spa from './routes/spa';

// register view engine for pigs
import { Pig } from './source/engines';
Expand All @@ -40,8 +41,9 @@ app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// register views
app.use('/', spa);
app.use('/migrate', migrate);
app.use('/', home);
app.use('/', spa);
app.use('/nfts', nfts);
app.use('/ppts', ppts);
app.use('/robots.txt', robots);
Expand Down
Binary file added public/images/jpg/desktop-mine.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/jpg/desktop-nfts.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/jpg/desktop-ppts.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/jpg/desktop-swap.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions routes/functions/env-of-mine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('env_of_mine', () => {
expect(env_of_mine(req as any)).toEqual({
...{
HEADER_ABOUT: '',
HEADER_HOME: '',
HEADER_MINE: '',
HEADER_NFTS: '',
HEADER_PPTS: '',
Expand Down
1 change: 1 addition & 0 deletions routes/functions/env-of.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('env_of', () => {
expect(env_of(req as any)).toEqual({
...{
HEADER_ABOUT: '',
HEADER_HOME: '',
HEADER_MINE: '',
HEADER_NFTS: '',
HEADER_PPTS: '',
Expand Down
2 changes: 2 additions & 0 deletions routes/functions/env-of.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ const header_page = (
) => {
const page = Pager.parse(req.path);
return {
HEADER_HOME:
page === Page.Home ? 'active' : '',
HEADER_MINE:
page === Page.Mine ? 'active' : '',
HEADER_NFTS:
Expand Down
39 changes: 39 additions & 0 deletions routes/home.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import request from 'supertest';
import app from '../app';

describe('GET /', () => {
let get: request.Test;
beforeEach(() => {
get = request(app).get('/');
});
it('should return w/an HTTP code = 302 Found', async () => {
await get.expect(302);
});
});
describe('GET /*/manifest.json', () => {
let get: request.Test;
beforeEach(() => {
get = request(app).get('/home/manifest.json');
});
it('should return w/an HTTP code = 302 Found', async () => {
await get.expect(302);
});
});
describe('GET /home', () => {
let get: request.Test;
beforeEach(() => {
get = request(app).get('/home');
});
it('should return w/an HTTP code = 200 OK', async () => {
await get.expect(200);
});
it('should return w/a Content-Type ~ html', async () => {
await get.expect('Content-Type', /html/)
});
it('should return w/a Content-Length > 0', async () => {
await get.expect((res) => {
const length = BigInt(res.headers['content-length']);
expect(length).toBeGreaterThan(0);
});
});
});
20 changes: 20 additions & 0 deletions routes/home.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Router } from 'express';
import { env_of } from './functions';
const router = Router();

/** REDIRECT to manifest.json. */
router.get(/\/[^/]+\/manifest\.json$/, (req, res) => {
res.redirect('/manifest.json');
});
/** REDIRECT to home page. */
router.get('/', (req, res) => {
res.redirect('/home');
});
/** GET home page. */
router.get('/home', (req, res) => {
res.render('home/home.pig', {
DESCRIPTION: 'Mine & Mint Proof-of-Work XPower Tokens',
TITLE: 'XPower', ...env_of(req),
});
});
export default router;
18 changes: 0 additions & 18 deletions routes/spa.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
import request from 'supertest';
import app from '../app';

describe('GET /', () => {
let get: request.Test;
beforeEach(() => {
get = request(app).get('/');
});
it('should return w/an HTTP code = 302 Found', async () => {
await get.expect(302);
});
});
describe('GET /*/manifest.json', () => {
let get: request.Test;
beforeEach(() => {
get = request(app).get('/mine/manifest.json');
});
it('should return w/an HTTP code = 302 Found', async () => {
await get.expect(302);
});
});
describe('GET /mine', () => {
let get: request.Test;
beforeEach(() => {
Expand Down
12 changes: 2 additions & 10 deletions routes/spa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,11 @@ import { join, sep } from 'path';
function routes(
spa_env: Record<string, string>
) {
/** REDIRECT to manifest.json. */
router.get(/\/[^/]+\/manifest\.json$/, (req, res) => {
res.redirect('/manifest.json');
});
/** REDIRECT to home page. */
router.get('/', (req, res) => {
res.redirect('/mine');
});
/** GET mine page. */
router.get('/mine', (req, res) => {
res.render('mine/mine.pig', {
DESCRIPTION: 'Mine & Mint Proof-of-Work XPower Tokens',
TITLE: 'XPower', ...env_of_mine(req), ...spa_env,
TITLE: 'XPower: Mine', ...env_of_mine(req), ...spa_env,
});
});
/** GET nfts page. */
Expand All @@ -35,7 +27,7 @@ function routes(
router.get('/stake', (req, res) => {
res.render('ppts/ppts.pig', {
DESCRIPTION: 'Stake minted XPower NFTs',
TITLE: 'XPower: Staking', ...env_of(req), ...spa_env
TITLE: 'XPower: Stake', ...env_of(req), ...spa_env
});
});
/** GET swap page. */
Expand Down
3 changes: 3 additions & 0 deletions source/redux/types/page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum Page {
None = 'none',
Home = 'home',
Mine = 'mine',
Nfts = 'nfts',
Ppts = 'stake',
Expand All @@ -22,6 +23,8 @@ export class Pager {
const suffix = path.length
? path[path.length - 1] : '';
switch (suffix.toLowerCase()) {
case 'home':
return Page.Home;
case 'mine':
return Page.Mine;
case 'nfts':
Expand Down
6 changes: 4 additions & 2 deletions source/services/location-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ export const LocationService = (
onPageSwitch(store, function syncLocationTitle(page) {
const titles: Record<Page, string> = {
[Page.None]: 'XPower',
[Page.Mine]: 'XPower',
[Page.Home]: 'XPower',
[Page.Mine]: 'XPower: Mine',
[Page.Nfts]: 'XPower: NFTs',
[Page.Ppts]: 'XPower: Staking',
[Page.Ppts]: 'XPower: Stake',
[Page.Swap]: 'XPower: Swap',
[Page.About]: 'XPower: About',
};
Expand All @@ -35,6 +36,7 @@ export const LocationService = (
);
const descriptions: Record<Page, string> = {
[Page.None]: 'Mine & Mint Proof-of-Work XPower Tokens',
[Page.Home]: 'Mine & Mint Proof-of-Work XPower Tokens',
[Page.Mine]: 'Mine & Mint Proof-of-Work XPower Tokens',
[Page.Nfts]: 'Mint stakeable XPower NFTs',
[Page.Ppts]: 'Stake minted XPower NFTs',
Expand Down
4 changes: 4 additions & 0 deletions views/header/header.pug
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
header
nav#menu.btn-group.nav.nav-pills.nav-justified.mb-3
a.btn.btn-outline-warning.flex-sm-fill.text-sm-center.nav-link.home(
class="{{HEADER_HOME}}" href="/home?token={{TOKEN}}"
)
i.bi-house-fill
a.btn.btn-outline-warning.flex-sm-fill.text-sm-center.nav-link.mine(
class="{{HEADER_MINE}}" href="/mine?token={{TOKEN}}"
)
Expand Down
10 changes: 9 additions & 1 deletion views/header/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ header {
color: var(--xp-gray-dark);
}
}
}
@media (min-width: 575px) {
nav#menu {
a.nav-link.home {
padding: 8px 0;
width: 0.5em;
}
}
}
}
26 changes: 18 additions & 8 deletions views/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function UiHeader(
<nav id='menu' className={
classes.join(' ')
}>
{$anchor(Page.Home, props)}
{$anchor(Page.Mine, props)}
{$anchor(Page.Nfts, props)}
{$anchor(Page.Ppts, props)}
Expand Down Expand Up @@ -55,28 +56,36 @@ const onClick = (dispatch: Dispatch) => (
{ page }: Pick<Props, 'page'>
) => {
if (e.ctrlKey === false) {
if (Page.None !== page) {
e.preventDefault();
switch (page) {
case Page.None: return;
case Page.Home: return;
default:
if (my_page !== Page.Home) {
e.preventDefault();
}
}
dispatch(switchPage(my_page));
}
}
function $icon(
my_page: Page
) {
const classes = [
'float-sm-start', icons[my_page]
];
const classes = (my_page !== Page.Home)
? ['float-sm-start', icons[my_page]]
: [icons[my_page]];
return <i className={classes.join(' ')} />;
}
function $label(
my_page: Page,
) {
return <span className='d-none d-sm-inline text'>
{labels[my_page]}
</span>;
if (my_page !== Page.Home) {
return <span className='d-none d-sm-inline text'>
{labels[my_page]}
</span>;
}
}
const icons: Record<Page, string> = {
[Page.Home]: 'bi-house-fill',
[Page.Mine]: 'bi-lightning-charge-fill',
[Page.Nfts]: 'bi-image-fill',
[Page.Ppts]: 'bi-cash-stack',
Expand All @@ -85,6 +94,7 @@ const icons: Record<Page, string> = {
[Page.None]: '',
}
const labels: Record<Page, string> = {
[Page.Home]: '',
[Page.Mine]: 'Mine',
[Page.Nfts]: 'NFTs',
[Page.Ppts]: 'Stake',
Expand Down
51 changes: 51 additions & 0 deletions views/home/content.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<div class="two-card">
<div class="lhs d-flex flex-column">
<h1>Mine Proof-of-Work XPOW</h1>
<p>Mining XPower XPOW tokens is simple and rewarding: By using computational power to solve complex puzzles, you earn tokens.</p>
<p>The effort you put into solving these puzzles ensures that everyone has a fair chance to acquire them &mdash; for widespread distribution.</p>
<div class="logo d-flex flex-grow-1 justify-content-center align-items-center">
<img src="images/svg/xpow.svg">
</div>
</div>
<div class="rhs">
<img src="/images/jpg/desktop-mine.jpg" height="1442" width="1002" alt="Mine XPOW" />
</div>
</div>
<hr />
<div class="two-card">
<div class="lhs d-flex flex-column">
<h1>Mint stakeable NFTs</h1>
<p>Creating XPower NFTs is unique: By depositing your XPOW, you can mint NFTs that represent something that's akin to bonds.</p>
<p>These NFTs are not only of artistic value but also functional, allowing you to stake them and earn rewards over time.</p>
<p class="emoji d-flex flex-grow-1 justify-content-center align-items-center">🖼️</p>
</div>
<div class="rhs">
<img src="/images/jpg/desktop-nfts.jpg" height="1442" width="1002" alt="Mint NFTs" />
</div>
</div>
<hr />
<div class="two-card">
<div class="lhs d-flex flex-column">
<h1>Claim APOW Rewards</h1>
<p>When you stake your XPower NFTs, you start earning APower APOW tokens: The longer you hold and stake your NFTs, the more APOW you accumulate.</p>
<p>This process ensures that your participation is continuously rewarded, making it an attractive option for those looking to maximize their involvement in the ecosystem.</p>
<div class="logo d-flex flex-grow-1 justify-content-center align-items-center">
<img src="images/svg/apow.svg">
</div>
</div>
<div class="rhs">
<img src="/images/jpg/desktop-ppts.jpg" height="1442" width="1002" alt="Claim APOW" />
</div>
</div>
<hr />
<div class="two-card">
<div class="lhs d-flex flex-column">
<h1>Swap XPOW & APOW</h1>
<p>You have the ability to seamlessly swap your XPower XPOW and APower APOW tokens on a decentralized exchange, offering flexibility and convenience in managing your assets.</p>
<p>Further, with the upcoming lending and borrowing feature, you'll be able to leverage your APOW as collateral to borrow XPOW or vice versa.</p>
<p class="emoji d-flex flex-grow-1 justify-content-center align-items-center">🏛️</p>
</div>
<div class="rhs">
<img src="/images/jpg/desktop-swap.jpg" height="1442" width="1002" alt="Swap Tokens" />
</div>
</div>
18 changes: 18 additions & 0 deletions views/home/home.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
extends ../app.pug

block styles
include ../theme/theme.pug

block globals
include ../global/contracts.pug
include ../global/urls.pug

block header
include ../header/header.pug

block content
content
div: include ./content.html

block footer
include ../footer/footer.pug
Loading

0 comments on commit cf353f6

Please sign in to comment.