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 25, 2024
1 parent 2c4e956 commit 3c86612
Show file tree
Hide file tree
Showing 21 changed files with 236 additions and 53 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.
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: 11 additions & 7 deletions routes/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ export const router = express.Router();
router.get('/', (req, res) => {
const params = new URLSearchParams(req.query as any);
res.render('migrate/index.pig', {
DESCRIPTION: 'Migrate old Tokens & NFTs to latest Version',
TITLE: 'XPower: Migrate', ...env_of(req),
VERSION_SRC: versionSource(params),
VERSION_SRC_CAPITALIZED: capitalize(versionSource(params)),
VERSION_TGT: versionTarget(params),
VERSION_TGT_CAPITALIZED: capitalize(versionTarget(params)),
...env
...{
DESCRIPTION: 'Migrate old Tokens & NFTs to latest Version',
TITLE: 'XPower: Migrate',
},
...{
VERSION_SRC: versionSource(params),
VERSION_SRC_CAPITALIZED: capitalize(versionSource(params)),
VERSION_TGT: versionTarget(params),
VERSION_TGT_CAPITALIZED: capitalize(versionTarget(params)),
},
...env_of(req), ...env
});
});
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
15 changes: 3 additions & 12 deletions routes/spa.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { env_of_mine } from './functions';
import { env_of } from './functions';
import { Router } from 'express';
const router = Router();
Expand All @@ -9,19 +8,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(req), ...spa_env,
});
});
/** GET nfts page. */
Expand All @@ -35,13 +26,13 @@ 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. */
router.get('/swap', (req, res) => {
res.render('swap/swap.pig', {
DESCRIPTION: 'Swap XPOW & APOW Tokens',
DESCRIPTION: 'Swap XPower & APower Tokens',
TITLE: 'XPower: Swap', ...env_of(req), ...spa_env
});
});
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
8 changes: 5 additions & 3 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,10 +36,11 @@ 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',
[Page.Swap]: 'Swap XPOW & APOW Tokens',
[Page.Swap]: 'Swap XPower & APower Tokens',
[Page.About]: 'Mine & Mint Proof-of-Work XPower Tokens',
};
if ($meta) {
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;
}
}
}
}
27 changes: 19 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 All @@ -42,6 +43,7 @@ function $anchor(
'nav-link', active
];
return <a
aria-label={labels[my_page]}
className={classes.join(' ')}
href={`/${my_page}?token=${token}`}
onClick={(e) => onClick(dispatch)(e, my_page, { page })}
Expand All @@ -55,28 +57,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 +95,7 @@ const icons: Record<Page, string> = {
[Page.None]: '',
}
const labels: Record<Page, string> = {
[Page.Home]: 'Home',
[Page.Mine]: 'Mine',
[Page.Nfts]: 'NFTs',
[Page.Ppts]: 'Stake',
Expand Down
1 change: 1 addition & 0 deletions views/home/content.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class=two-card><div class="d-flex flex-column lhs"><h1>Mine & Mint Proof-of-Work XPower Tokens</h1><p>Mining XPower <strong>XPOW</strong> tokens is simple and rewarding: By using computational power to solve complex puzzles, you can earn tokens.<p>The effort put into solving these puzzles ensures that everyone has a fair chance to acquire them — for widespread distribution.<div class="align-items-center d-none d-sm-flex flex-grow-1 justify-content-center logo"><img alt="XPOW logo"height=128 src=images/svg/xpow.svg width=128></div></div><div class=rhs><img alt="Mine XPOW"height=1442 src=/images/jpg/desktop-mine.jpg width=1002></div></div><hr><div class=two-card><div class="d-flex flex-column lhs"><h1>Mint stakeable XPower NFTs</h1><p>Creating XPower NFTs is unique: By depositing your <strong>XPOW</strong>, you can mint NFTs that represent something that's similar to bonds.<p>These NFTs are not only of artistic value but also functional, allowing you to stake them and earn rewards over time.<p class="align-items-center d-none d-sm-flex flex-grow-1 justify-content-center emoji">🖼️</div><div class=rhs><img alt="Mint NFTs"height=1442 src=/images/jpg/desktop-nfts.jpg width=1002></div></div><hr><div class=two-card><div class="d-flex flex-column lhs"><h1>Claim APower Token Rewards</h1><p>When you stake your XPower NFTs, you start earning APower <strong>APOW</strong> tokens: The longer you hold and stake your NFTs, the more <strong>APOW</strong> you accumulate.<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.<div class="align-items-center d-none d-sm-flex flex-grow-1 justify-content-center logo"><img alt="APOW logo"height=128 src=images/svg/apow.svg width=128></div></div><div class=rhs><img alt="Claim APOW"height=1442 src=/images/jpg/desktop-ppts.jpg width=1002></div></div><hr><div class=two-card><div class="d-flex flex-column lhs"><h1>Swap XPower & APower Tokens</h1><p>You have the ability to seamlessly swap your XPower <strong>XPOW</strong> and APower <strong>APOW</strong> tokens on a decentralized exchange, offering flexibility and convenience in managing your assets.<p>Further, with the upcoming lending and borrowing feature, you'll be able to leverage your <strong>APOW</strong> as collateral to borrow <strong>XPOW</strong> or vice versa.<p class="align-items-center d-none d-sm-flex flex-grow-1 justify-content-center emoji">🏛️</div><div class=rhs><img alt="Swap XPOW & APOW"height=1442 src=/images/jpg/desktop-swap.jpg width=1002></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 3c86612

Please sign in to comment.