Skip to content

Commit

Permalink
Code state at end of lecture.
Browse files Browse the repository at this point in the history
  • Loading branch information
arvind committed Oct 5, 2023
1 parent f9f352d commit 8500c9d
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 115 deletions.
4 changes: 2 additions & 2 deletions src/About.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<template v-slot:subtitle>About Cartoons</template>
</Header>

<p>
<p v-if="$route.params.persona === 'pirate'">
Pirate avast take a caulk smartly Cat o'nine tails splice the main brace gaff gun barque lugsail. Doubloon provost chandler driver ho poop deck boom bilged on her anchor man-of-war gally. Log draft crow's nest chase scuppers clap of thunder tender ballast starboard hands.
</p>

<p>
<p v-if="$route.params.persona === 'hipster'">
Kickstarter waistcoat flexitarian praxis pop-up. Banjo next level kinfolk literally asymmetrical jianbing tilde fanny pack food truck listicle. Banjo adaptogen cliche raw denim semiotics cold-pressed. Edison bulb fanny pack tumeric taxidermy authentic. Yes plz microdosing salvia gatekeep post-ironic same mixtape tilde cronut. Palo santo 3 wolf moon cupping, gochujang meggings chambray man bun aesthetic PBR&B vape. Coloring book pickled yr, kickstarter art party put a bird on it vibecession man bun beard.
</p>
</template>
95 changes: 2 additions & 93 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,94 +1,3 @@
<script setup lang="ts">
import {ref, computed} from 'vue';
import Header from '@/components/Header.vue';
const message = ref('Hello 6.1040 Fall 2023!');
const reversedMsg = computed(() => {
return message.value.split('').reverse().join('');
});
const colors = ref([
{value: 0},
{value: 0},
{value: 0}
]);
const rgb = ref('rgb(0, 0, 0)');
function setColor() {
const colorVal = colors.value.map(c => c.value); // [0, 0, 0]
rgb.value = `rgb(${colorVal.join(', ')})`;
}
const cartoons = ref([
{
title: "ThunderCats",
desc: "ThunderCats is an American media franchise, featuring a fictional group of cat-like humanoid aliens.",
votes: {yay: 7, nay: 3}
},
{
title: "Captain Planet",
desc: "Our world is in peril. Gaia, the spirit of the Earth, can no longer stand the terrible destruction plaguing our planet. She sends five magic rings to five special young people.",
votes: {yay: 8, nay: 2}
},
{
title: "Top Cat",
desc: "The title character is the leader of a gang of Manhattan alley cats who constantly hatch get-rich-quick schemes through scams, but most of them usually backfire.",
votes: {yay: 1, nay: 9}
},
{
title: "Dexter's Labratory",
desc: "The series follows Dexter, an enthusiastic boy-genius with a hidden science laboratory in his room full of inventions, which he keeps secret from his clueless parents.",
votes: {yay: 6, nay: 4}
}
]);
</script>

<template>
<Header />

<h1>
{{ message }}
</h1>

<p>
{{ reversedMsg }}
</p>

<h2>Two-way Data Bind</h2>

<ol>
<li>Changing a reactive variable (e.g., in JavaScript/TypeScript) automatically re-render the DOM</li>
<li>Manipulating a DOM element (e.g., a textbox/slider/etc.) automatically update a reactive variable</li>
</ol>

<p>
1: <input type="text"
v-bind:value="message" />
</p>

<p>
2: <input type="text"
v-on:input="event => message = event.target.value" />
</p>

<p>
1 & 2: <input type="text" v-model="message" />
</p>

<div v-bind:style="{background: rgb}">
<p v-for="c in colors">
<input type="range" min="0" max="255" step="1"
v-model="c.value"> {{ c.value }}
</p>

<button v-on:click="setColor">Set Color</button>
</div>

<template>
<router-view></router-view>
</template>

<style>
</style>
106 changes: 106 additions & 0 deletions src/Home.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<script setup lang="ts">
import {ref, computed} from 'vue';
import Header from '@/components/Header.vue';
import Cartoon from '@/components/Cartoon.vue';
const message = ref('Hello 6.1040 Fall 2023!');
const reversedMsg = computed(() => {
return message.value.split('').reverse().join('');
});
const colors = ref([
{value: 0},
{value: 0},
{value: 0}
]);
const rgb = ref('rgb(0, 0, 0)');
function setColor() {
const colorVal = colors.value.map(c => c.value); // [0, 0, 0]
rgb.value = `rgb(${colorVal.join(', ')})`;
}
const cartoons = ref([
{
title: "ThunderCats",
desc: "ThunderCats is an American media franchise, featuring a fictional group of cat-like humanoid aliens.",
votes: {yay: 7, nay: 3}
},
{
title: "Captain Planet",
desc: "Our world is in peril. Gaia, the spirit of the Earth, can no longer stand the terrible destruction plaguing our planet. She sends five magic rings to five special young people.",
votes: {yay: 8, nay: 2}
},
{
title: "Top Cat",
desc: "The title character is the leader of a gang of Manhattan alley cats who constantly hatch get-rich-quick schemes through scams, but most of them usually backfire.",
votes: {yay: 1, nay: 9}
},
{
title: "Dexter's Labratory",
desc: "The series follows Dexter, an enthusiastic boy-genius with a hidden science laboratory in his room full of inventions, which he keeps secret from his clueless parents.",
votes: {yay: 6, nay: 4}
}
]);
</script>

<template>
<Header>
<template v-slot:subtitle>
{{message}}
</template>

<template v-slot:slogan>
{{reversedMsg}}
</template>
</Header>

<Cartoon v-for="toon in cartoons"
v-bind="toon" />

<h1>
{{ message }}
</h1>

<p>
{{ reversedMsg }}
</p>

<h2>Two-way Data Bind</h2>

<ol>
<li>Changing a reactive variable (e.g., in JavaScript/TypeScript) automatically re-render the DOM</li>
<li>Manipulating a DOM element (e.g., a textbox/slider/etc.) automatically update a reactive variable</li>
</ol>

<p>
1: <input type="text"
v-bind:value="message" />
</p>

<p>
2: <input type="text"
v-on:input="event => message = event.target.value" />
</p>

<p>
1 & 2: <input type="text" v-model="message" />
</p>

<div v-bind:style="{background: rgb}">
<p v-for="c in colors">
<input type="range" min="0" max="255" step="1"
v-model="c.value"> {{ c.value }}
</p>

<button v-on:click="setColor">Set Color</button>
</div>

</template>

<style>
</style>
21 changes: 8 additions & 13 deletions src/components/Auth.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
<script setup lang="ts">
import md5 from 'md5';
import {ref, computed} from 'vue';
import {computed} from 'vue';
import { useAuthStore } from '@/stores/auth';
const email = ref('');
const store = useAuthStore();
const authenticated = ref(false);
function toggleAuth() {
authenticated.value = email.value !== '' && !authenticated.value;
}
const gravatar = computed(() => `http://www.gravatar.com/avatar/${md5(email.value)}`);
const gravatar = computed(() => `http://www.gravatar.com/avatar/${md5(store.email)}`);
</script>

<template>
<div id="auth">
<img v-if="authenticated" v-bind:src="gravatar" width="50" />
<img v-if="store.authenticated" v-bind:src="gravatar" width="50" />

<input type="text" v-model="email" placeholder="email address" />
<input type="text" v-model="store.email" placeholder="email address" />

<button v-if="!authenticated" v-on:click="toggleAuth">Login</button>
<button v-if="!store.authenticated" v-on:click="store.toggleAuth">Login</button>

<button v-if="authenticated" v-on:click="toggleAuth">Logout</button>
<button v-if="store.authenticated" v-on:click="store.toggleAuth">Logout</button>
</div>
</template>

Expand Down
13 changes: 11 additions & 2 deletions src/components/Cartoon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@
const props = defineProps(['title', 'desc', 'votes']);
const total = ref(props.votes.yay - props.votes.nay);
function handleVotedEvents(yayVotes, nayVotes) {
total.value = yayVotes - nayVotes;
}
const opacity = computed(() => {
return Math.max(0.1, total.value/10);
});
</script>

<template>
<div class="toon">
<div class="toon" v-bind:style="{opacity}">
<h2>{{ props.title }} ({{ total }} points)</h2>
<p>{{ props.desc }}</p>
<Vote v-bind="votes" />
<Vote v-bind="props.votes"
v-on:voted="handleVotedEvents" />
</div>
</template>

Expand Down
18 changes: 18 additions & 0 deletions src/components/Header.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
<script setup lang="ts">
import { computed } from 'vue';
import Auth from './Auth.vue';
import { useAuthStore } from '@/stores/auth';
const store = useAuthStore();
const homeLink = computed(() => store.authenticated ? '/home' : '/');
</script>

<template>
<div id="header">
<h1>I am the Header Component</h1>
<h2>
<slot name="subtitle"></slot>
</h2>

<Auth />

<slot name="slogan"></slot>

<p>
<router-link v-bind:to="homeLink">Home</router-link> &nbsp;
<router-link to="/about/pirate">About Pirates</router-link> &nbsp;
<router-link to="/about/hipster">About Hipster</router-link>
</p>
</div>
</template>

Expand Down
26 changes: 23 additions & 3 deletions src/components/Vote.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
<script setup lang="ts">
import {ref, defineProps, defineEmits} from 'vue';
import { useAuthStore } from '@/stores/auth';
const props = defineProps(['yay', 'nay']);
const emit = defineEmits(['voted']);
const store = useAuthStore();
// Props are readonly. To be able to change the votes,
// we need to derive new reactive variables.
const yay = ref(props.yay);
const nay = ref(props.nay);
function voteYay() {
yay.value++;
emit('voted', yay.value, nay.value);
}
function voteNay() {
nay.value++;
emit('voted', yay.value, nay.value);
}
</script>

<template>
<p>
<button>🥳 ({{ yay }})</button>
<button>🤢 ({{ nay }})</button>
<p v-if="store.authenticated">
<button v-on:click="voteYay">🥳 ({{ yay }})</button>
<button v-on:click="voteNay">🤢 ({{ nay }})</button>
</p>
</template>

Expand Down
9 changes: 7 additions & 2 deletions src/router.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { createRouter, createWebHistory } from 'vue-router';
import App from '@/App.vue';
import Home from '@/Home.vue';
import AboutVue from './About.vue';

const router = createRouter({
history: createWebHistory(),

routes: [
{
path: '/',
component: App
component: Home
},
{
path: '/about/:persona',
component: AboutVue
}
]
});
Expand Down
14 changes: 14 additions & 0 deletions src/stores/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {ref, computed} from 'vue';
import { defineStore } from 'pinia';

export const useAuthStore = defineStore('auth', () => {
const email = ref('');

const authenticated = ref(false);

function toggleAuth() {
authenticated.value = email.value !== '' && !authenticated.value;
}

return {email, authenticated, toggleAuth}
});

0 comments on commit 8500c9d

Please sign in to comment.