Browse Source

Make the header hero more interesting.

master
Zed A. Shaw 1 month ago
parent
commit
5243d00f4c
  1. 4
      .gitignore
  2. 103
      client/pages/Home.svelte
  3. 41
      client/routes.js
  4. 131
      rendered/pages/index.svelte
  5. 2
      static/color.css
  6. 35
      static/global.css
  7. 9
      static/images/header.svg

4
.gitignore

@ -10,7 +10,3 @@ debug/
static/thumbs
static/videos
secrets/*
client/pages/Home.svelte
rendered/pages/index.svelte
client/routes.js
client/config.js

103
client/pages/Home.svelte

@ -0,0 +1,103 @@
<script>
import { link } from 'svelte-spa-router';
import { onMount } from 'svelte';
import api from "$/client/api.js";
import Icon from "$/client/components/Icon.svelte";
import { defer } from "$/client/lib/helpers.js";
import IconImage from '$/client/components/IconImage.svelte';
import SnapImage from "$/client/components/SnapImage.svelte";
import Layout from "$/client/Layout.svelte";
import { user } from "$/client/stores.js";
import { course_id } from "$/client/config.js";
import Spinner from "$/client/components/Spinner.svelte";
let course = {modules: [], title: "", description: ""};
let course_promise = defer("course_promise");
const load_course = async () => {
const [status, data] = await api.get(`/api/course?course_id=${course_id}`, api.logout_user);
course = status == 200 ? data : {modules: [], title: "", description: ""};
}
const user_paid = async () => {
const [status, data] = await api.get('/api/user/payments', api.logout_user);
$user.paid = status == 200 ? data.paid : false;
}
onMount(async () => {
await load_course();
course_promise.resolve();
await user_paid();
});
</script>
<style>
modules {
display: flex;
flex-direction: column;
width: 100%;
}
modules card {
margin-top: 2rem;
}
card top img {
width: 100%;
}
</style>
<Layout authenticated={ true } testid="home-page">
{#await course_promise}
<Spinner color="var(--value4)" aspect_ratio="16/9" />
{:then}
<h1>Modules</h1>
<callout>
<p>{ course.description }</p>
</callout>
<modules>
{#each course.modules as module}
<card>
<top>
{#if module.poster}
<figure>
<SnapImage src={ module.poster} />
</figure>
{:else}
<IconImage width={ 16 * 60 } height={ 9 * 60 } name="video" />
{/if}
</top>
<middle>
<h4>
{ module.title }
</h4>
<p>{ module.description }</p>
</middle>
<bottom>
<button-group>
<button>
{#if module.is_free || $user.paid }
<a href="/module/{ module.id }/" use:link>
<Icon name="book-open" color="var(--color-bg)" size="48"/>
<tooltip class="top">Study this module.</tooltip>
</a>
{:else}
<a href="/purchase/" use:link>
<Icon name="credit-card" color="var(--color-bg)" size="48"/>
<tooltip class="top">Buy the course</tooltip>
</a>
{/if}
</button>
</button-group>
</bottom>
</card>
{/each}
</modules>
{/await}
</Layout>

41
client/routes.js

@ -0,0 +1,41 @@
import Register from './pages/Register.svelte';
import Login from './pages/Login.svelte';
import AdminIndex from './pages/admin/index.svelte';
import AdminCreate from './pages/admin/Create.svelte';
import AdminTable from './pages/admin/Table.svelte';
import AdminReadUpdate from './pages/admin/ReadUpdate.svelte';
import UserProfile from './pages/UserProfile.svelte';
import ResetPassword from './pages/ResetPassword.svelte';
import Module from './pages/Module.svelte';
import Lesson from './pages/Lesson.svelte';
import Unsubscribe from './pages/Unsubscribe.svelte';
import Home from './pages/Home.svelte';
import NotFound from './pages/NotFound.svelte';
/* #if process.env.DANGER_ADMIN
import Components from './bando/Components.svelte';
import EmailConfig from './pages/admin/EmailConfig.svelte';
// #endif */
import Purchase from "./pages/Purchase.svelte";
import TOS from "./pages/TOS.svelte";
export default {
'/register/': Register,
'/login/': Login,
'/forgot/': ResetPassword,
'/profile/': UserProfile,
'/tos/': TOS,
'/purchase/': Purchase,
'/module/:module_id/': Module,
'/lesson/:lesson_id/': Lesson,
'/email/unsubscribe/:unsubkey/': Unsubscribe,
'/admin/table/create/:table/': AdminCreate,
'/admin/table/:table/': AdminTable,
'/admin/table/:table/:row_id/': AdminReadUpdate,
'/admin/table/': AdminIndex,
/* #if process.env.DANGER_ADMIN
'/admin/email/': EmailConfig,
'/bando/components/:name?': Components,
// #endif */
'/': Home,
'*': NotFound,
}

131
rendered/pages/index.svelte

@ -0,0 +1,131 @@
<script>
import Layout from '../Layout.svelte';
</script>
<style>
hero.middle {
border-radius: 0px 0px var(--border-radius) var(--border-radius);
}
callout.hero {
background: var(--color-bg-inverted);
color: var(--color-text-inverted);
border-radius: 10px 10px 0px 0px;
margin-bottom: 0px;
}
hero.quote img {
width: 50%;
}
main h2 {
text-align: center;
}
main {
font-size: 1.3em;
}
hero.quote {
margin-left: -10px;
margin-right: -10px;
display: flex;
flex-direction: row;
background-color: var(--color-bg-secondary);
}
span#slogan {
font-family: var(--font-computer);
font-size: 1.5em;
}
section {
margin-right: 2rem;
margin-left: 2rem;
font-size: 1.2em;
}
hero figure img {
filter: invert(var(--invert-level));
}
</style>
<Layout bare={ true }>
<hero>
<figure>
<img src="/images/header.svg" />
</figure>
<cover>
<img src="/images/logo.svg" />
<span id="slogan">LOGIC ^ ART ^ TRUTH</span>
<a href="/client/#/register/"><i>Register for Free</i></a>
</cover>
</hero>
<main>
<h2>The XOR Mission</h2>
<section>
<p>The XOR Academy is an <b>avocational</b> (meaning not meant for vocational training) art course with the mission of disproving the notion that people are either "logical" xor "creative" by teaching anyone to paint what they see in a gradual and logical way.</p>
<p>The slogan <code>LOGIC ^ ART ^ TRUTH</code> comes from the XOR operation in computers which uses the symbol <code>^</code>. An <b>Exclusive OR (XOR)</b> means that two statements can be true, or false, but both can't be true. An interesting property of <code>XOR</code> is it undoes a previous <code>XOR</code>, so we can undo the belief of <code>LOGIC ^ ART</code> with <code>^ TRUTH</code>.
</p>
<p>This project accomplishes this goal by teaching people how to paint what they see as a way to study the <b>TRUTH</b> of the reality of what they perceive. By studying this style of painting it's hoped that people will learn about their world and realize that they don't have to be an "artist" to enjoy the truth of their visual experience.
</p>
</section>
<hero class="quote">
<blockquote>
"Photography is an art. It forces artists to discard their old routine and forget their old formulas. It has opened our eyes and forced us to see that which previously we have not seen; a great and inexpressible service for Art. It is thanks to photography that Truth has finally come out of her well. She will never go back."
<footer>Jean-Léon Gérôme</footer>
</blockquote>
<img src="/images/truth.jpg" />
</hero>
<h2>Course Curriculum</h2>
<section>
<aside>
<ol>
<li>Your First Oil Painting</li>
<li>Monochrome Study Projects</li>
<li>Mixing Colors Level 1</li>
<li>Your First Color Painting</li>
<li>Mixing Colors Level 2</li>
<li>Your First Full Color Painting</li>
</ol>
</aside>
<aside>
There are also weekly live demos and painting
sessions for you to watch or follow along. <b>No
participation necessary</b>. Simply come and enjoy
learning or watching, and if you want attempt
the same painting.
</aside>
</section>
<section>
<h2>Pay What's Fair</h2>
<p>The XOR Academy uses a "Pay What's Fair" model that lets you pay what you think the course is worth after you are sure you want to study more. After you <a href="/client/#/register">register</a> you'll be able to try the first module with no obligation to pay. If you wish to continue then you'll be asked to pay what's fair to continue. Doing this allows people who can't afford the course to still study, and lets those who can afford it to help pay for the course's expenses.
</p>
<a href="/client/#/register"><h3><i>Register Today for Free</i></h3></a>
</section>
<hr>
<h2>About The Teacher</h2>
<hero class="quote">
<blockquote>
Zed A. Shaw is a programmer by day and a painter by day. He's been painting and drawing since 2013 and programming for even longer. His primary artistic interests are landscape painting, painting outside (known as Plein Air Painting), and self-portraits. You can follow him on <a href="https://www.instagram.com/zedshaw/">Instagram @zedshaw</a>.
</blockquote>
<img src="/images/zed.png"/>
</hero>
<hr>
</main>
</Layout>

2
static/color.css

@ -73,9 +73,11 @@
--width-content: 1700px;
--width-badge: 20px;
--font-size-badge: 13px;
--invert-level: 0;
}
[data-theme="dark"] {
--invert-level: 1;
--color: var(--value8);
--color-accent: var(--value7);
--color-icon-image: var(--value8);

35
static/global.css

@ -864,8 +864,7 @@ badge {
bottom: 5px;
left: 5px;
}
callout {
gcallout {
background-color: var(--color-bg-inverted);
color: var(--color-text-inverted);
display: flex;
@ -1132,9 +1131,7 @@ label.large::after {
height: 3rem;
}
hero {
background-color: var(--color-bg-secondary);
display: flex;
flex-direction: column;
justify-content: center;
@ -1151,8 +1148,12 @@ hero figure {
padding: 0;
}
hero:hover figure {
opacity: 0.2;
z-index: -1;
}
hero cover {
hero > cover {
display: flex;
flex-direction: column;
align-items: center;
@ -1165,11 +1166,15 @@ hero cover {
right: 0;
font-size: 4vw;
color: var(--color-overlay-text);
background: var(--color-overlay-background);
transition: background 0.5s ease-out;
opacity: 0;
}
hero:hover cover {
opacity: 1;
z-index: -1;
}
hero cover h1 {
margin-top: 0;
margin-bottom: 0;
@ -1183,24 +1188,11 @@ hero cover:hover a i {
opacity: 100%;
}
hero cover a i {
background-color: var(--color-bg-inverted);
hero over a i {
color: var(--color-text-inverted);
border: 2px solid var(--value0);
text-shadow: none;
}
hero.main:hover figure {
transform: scale(1.03);
filter: blur(4px);
}
hero.main:hover img {
opacity: 0.2;
}
hero.main:hover cover {
opacity: 1;
font-size: 0.5em;
}
hero.middle {
@ -1226,7 +1218,6 @@ hero.middle button {
hero.middle section aside {
background-color: var(--color-bg);
}
breadcrumb {
background-color: var(--color-bg-tertiary);
display: flex;

9
static/images/header.svg

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 857 B

After

Width:  |  Height:  |  Size: 6.3 KiB

Loading…
Cancel
Save