Created
January 23, 2021 15:13
-
-
Save jsutterfield/0afd6e93d79956e662f28be8c2a6beaa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div id="app" class="tinder-app"> | |
<MatchModal | |
v-if="showMatchModal" | |
:gender="latestMatchGender" | |
:name="latestMatchName" | |
v-on:click.native="showMatchModal = false" | |
/> | |
<ConnectAccountsModal | |
v-if="showConnectModal" | |
@close-connect-modal="closeConnectModal" | |
/> | |
<OutOfNamesModal | |
v-if="showOutOfNamesModal" | |
:namesCount="countOfNamesWithCurrentFilters" | |
/> | |
<div class="tinder-container"> | |
<Tinder | |
ref="tinder" | |
:queue.sync="queue" | |
:offset-y="0.75" | |
offsetUnit="rem" | |
@submit="onSubmit" | |
key-name="id" | |
> | |
<template slot-scope="nameObject"> | |
<div | |
class="card" | |
:class="[ | |
{ | |
boycard: nameObject.data.gender === 'm', | |
girlcard: nameObject.data.gender === 'f' | |
} | |
]" | |
> | |
<div :style="{ marginBottom: lastName ? '1rem' : '2rem' }"> | |
<h3>{{ nameObject.data.name }}</h3> | |
<h4 v-if="lastName">{{ lastName }}</h4> | |
</div> | |
<img svg-inline class="card__feet" src="../../svg/feet.svg" /> | |
</div> | |
</template> | |
<div class="like-pointer" slot="like"> | |
<p>Like</p> | |
</div> | |
<div class="nope-pointer" slot="nope"> | |
<p>Nope</p> | |
</div> | |
</Tinder> | |
<div class="tinder-buttons"> | |
<div class="tinder-button" @click="decide('nope')"> | |
<img svg-inline class="tinder-button__x" src="../../svg/x.svg" /> | |
</div> | |
<div | |
class="tinder-button tinder-button--small" | |
@click="decide('rewind')" | |
> | |
<img | |
svg-inline | |
class="tinder-button__go_back" | |
src="../../svg/go_back.svg" | |
/> | |
</div> | |
<div class="tinder-button" @click="decide('like')"> | |
<img | |
svg-inline | |
class="tinder-button__heart" | |
src="../../svg/heart.svg" | |
/> | |
</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<script> | |
import Tinder from "vue-tinder"; | |
import MatchModal from "./MatchModal.vue"; | |
import ConnectAccountsModal from "./ConnectAccountsModal.vue"; | |
import OutOfNamesModal from "./OutOfNamesModal.vue"; | |
import axios from "axios"; | |
import Cookies from "js-cookie"; | |
export default { | |
name: "App", | |
components: { Tinder, MatchModal, ConnectAccountsModal, OutOfNamesModal }, | |
data() { | |
const MyAccount = window.SwipeNames; | |
return { | |
queue: [], | |
history: [], | |
lastName: null, | |
latestMatchName: null, | |
latestMatchGender: null, | |
showMatchModal: false, | |
showConnectModal: false, | |
showOutOfNamesModal: false, | |
countOfNamesWithCurrentFilters: 0, | |
shouldShowConnectModal: MyAccount.shouldShowConnectModal | |
}; | |
}, | |
created() { | |
this.fetchMoreNames(); | |
}, | |
methods: { | |
onSubmit({ type, item, key }) { | |
this.history.push(item); | |
// TODO clean this up a bit | |
const like_url = `/api/names/${key}/like`; | |
const dislike_url = `/api/names/${key}/dislike`; | |
const url_to_use = type === "like" ? like_url : dislike_url; | |
const csrf_token = Cookies.get("csrftoken"); | |
axios | |
.post(url_to_use, null, { | |
headers: { "X-CSRFToken": csrf_token } | |
}) | |
.then(response => { | |
if (this.queue.length === 0) { | |
this.fetchMoreNames(); | |
} | |
const data = response.data; | |
if (data.member_of_group_likes_name) { | |
const liked_name = response.data.name; | |
this.latestMatchName = liked_name.text; | |
this.latestMatchGender = liked_name.gender; | |
this.showMatchModal = true; | |
} | |
if (this.history.length === 20 && this.shouldShowConnectModal) { | |
this.showConnectModal = true; | |
axios.post("/api/users/set-has-seen-connect-modal", null, { | |
headers: { "X-CSRFToken": csrf_token } | |
}); | |
} | |
}); | |
}, | |
fetchMoreNames() { | |
const vm = this; | |
axios.get("/api/names").then(response => { | |
// TODO add error handling | |
const data = response.data; | |
vm.queue = vm.queue.concat(data.names); | |
vm.lastName = data.last_name; | |
if (vm.queue.length === 0) { | |
axios.get("/api/users/count-of-names").then(response => { | |
vm.countOfNamesWithCurrentFilters = response.data.count; | |
vm.showOutOfNamesModal = true; | |
}); | |
} | |
}); | |
}, | |
async decide(choice) { | |
if (choice === "rewind") { | |
if (this.history.length) { | |
this.$refs.tinder.rewind([this.history.pop()]); | |
} | |
} else { | |
this.$refs.tinder.decide(choice); | |
} | |
}, | |
closeConnectModal() { | |
this.showConnectModal = false; | |
this.shouldShowConnectModal = false; | |
} | |
} | |
}; | |
</script> | |
<style lang="scss"> | |
@import "../../sass/abstract/variables"; | |
@import "../../sass/abstract/mixins"; | |
.tinder-app { | |
text-align: center; | |
} | |
.tinder-container { | |
display: inline-flex; | |
flex-direction: column; | |
align-items: center; | |
margin-top: 20vh; | |
margin-bottom: 5rem; | |
@include respond($phone-landscape) { | |
// margin-top: 10rem; | |
} | |
@include respond($phone) { | |
margin-top: 22vh; | |
} | |
} | |
.vue-tinder { | |
width: 30rem; | |
height: 30rem; | |
} | |
.card { | |
width: 100%; | |
height: 100%; | |
text-align: center; | |
padding-top: 2rem; | |
&__feet { | |
height: 12rem; | |
width: 12rem; | |
margin-top: 1rem; | |
} | |
h3 { | |
font-size: 5rem; | |
font-family: $oswald-font-family; | |
letter-spacing: 0.3rem; | |
margin-bottom: -1rem; | |
} | |
h4 { | |
font-size: 2.5rem; | |
} | |
} | |
.boycard { | |
background-color: $color-boy-card; | |
.card__feet { | |
fill: $color-boy-feet; | |
} | |
} | |
.girlcard { | |
background-color: $color-girl-card; | |
.card__feet { | |
fill: $color-girl-feet; | |
} | |
} | |
.tinder-buttons { | |
display: flex; | |
margin-top: 4rem; | |
align-items: center; | |
} | |
.tinder-button { | |
background-color: $color-white; | |
border-radius: 500%; | |
margin: 0 2rem; | |
height: 7rem; | |
width: 7rem; | |
position: relative; | |
cursor: pointer; | |
&:active { | |
transform: translateY(0.2rem); | |
box-shadow: 0 0.5rem 1rem rgba($color-black, 0.2); | |
} | |
svg { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translateY(-50%) translateX(-50%); | |
height: 4rem; | |
width: 4rem; | |
&:focus { | |
outline: none; | |
} | |
} | |
&__x { | |
fill: $color-black; | |
} | |
&__heart { | |
fill: $color-primary-orange; | |
} | |
&__go_back { | |
fill: #00a79d; | |
} | |
&--small { | |
height: 4rem; | |
width: 4rem; | |
svg { | |
height: 2.5rem; | |
width: 2.5rem; | |
} | |
} | |
} | |
.nope-pointer, | |
.like-pointer { | |
position: absolute; | |
z-index: 1; | |
top: 2rem; | |
font-family: $oswald-font-family; | |
padding: 0 1rem; | |
border: 2px solid $color-white; | |
border-radius: 2px; | |
text-transform: uppercase; | |
font-size: 3rem; | |
line-height: 1.2; | |
p { | |
padding: 0; | |
margin: 0; | |
} | |
} | |
.like-pointer { | |
left: 2rem; | |
transform: rotate(-20deg); | |
} | |
.nope-pointer { | |
right: 2rem; | |
transform: rotate(20deg); | |
} | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require("path"); | |
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); | |
const BundleTracker = require("webpack-bundle-tracker"); | |
const { VueLoaderPlugin } = require("vue-loader"); | |
module.exports = { | |
entry: { | |
contact: "./app/static/sass/pages/contact.scss", | |
home: "./app/static/sass/pages/home.scss", | |
name_preferences_styles: "./app/static/sass/pages/name_preferences.scss", | |
name_preferences_js: [ | |
"./app/static/javascript/name_preferences.js", | |
"./app/static/javascript/theme_buttons.js" | |
], | |
swipe_names_styles: "./app/static/sass/pages/swipe_names.scss", | |
swipe_names_app: [ | |
"./app/static/javascript/swipe_names.js", | |
"./app/static/javascript/theme_buttons.js" | |
], | |
names_list_styles: "./app/static/sass/pages/names_list.scss", | |
names_list_js: "./app/static/javascript/names_list.js", | |
add_name_modal: "./app/static/javascript/add_name_modal.js", | |
sentry: "./app/static/javascript/sentry_bootstrap.js", | |
login: "./app/static/sass/pages/login.scss", | |
create_account: "./app/static/sass/pages/create_account.scss", | |
connect: "./app/static/sass/pages/connect.scss", | |
connections: "./app/static/sass/pages/connections.scss", | |
confirm_connection: "./app/static/sass/pages/confirm_connection.scss", | |
connect_error: "./app/static/sass/pages/connect_error.scss", | |
four_oh_four: "./app/static/sass/pages/404.scss", | |
password_reset: "./app/static/sass/pages/password_reset.scss", | |
success: "./app/static/sass/pages/success.scss", | |
// prettier-ignore | |
password_reset_confirm: "./app/static/sass/pages/password_reset_confirm.scss", | |
// prettier-ignore | |
accounts_form_button_enable_js: "./accounts/static/javascript/accounts_form_button_enable.js", | |
my_account_js: "./app/static/javascript/my_account.js", | |
my_account_styles: "./app/static/sass/pages/my_account.scss", | |
unsubscribe: "./app/static/sass/pages/unsubscribe.scss" | |
}, | |
output: { | |
path: path.resolve("./app/static/bundles/"), | |
filename: "[name]-[hash].js" | |
}, | |
module: { | |
rules: [ | |
{ | |
test: /\.js$/, | |
loader: "babel-loader" | |
}, | |
{ | |
test: /\.(woff|ttf)/, | |
use: [ | |
{ | |
loader: "file-loader", | |
options: { | |
name: "[name].[ext]", | |
outputPath: "fonts/" | |
} | |
} | |
] | |
}, | |
{ | |
test: /\.(png|svg|jpg|gif)$/, | |
use: [ | |
{ | |
loader: "file-loader", | |
options: { | |
esModule: false, | |
publicPath: "/static/bundles/" | |
} | |
} | |
] | |
}, | |
{ | |
test: /\.(sa|sc|c)ss$/, | |
use: [ | |
{ | |
loader: MiniCssExtractPlugin.loader | |
}, | |
{ | |
loader: "css-loader" | |
}, | |
// { | |
// // Then we apply postCSS fixes like autoprefixer and minifying | |
// TODO add this to the production build | |
// loader: "postcss-loader" | |
// }, | |
{ | |
loader: "sass-loader", | |
options: { | |
implementation: require("sass") | |
} | |
} | |
] | |
}, | |
{ | |
test: /\.vue$/, | |
use: [ | |
{ | |
loader: "vue-loader" | |
}, | |
{ | |
loader: "vue-svg-inline-loader" | |
} | |
] | |
} | |
] | |
}, | |
plugins: [ | |
new MiniCssExtractPlugin({ filename: "[name]-[hash].css" }), | |
new BundleTracker({ filename: "./webpack-stats.json" }), | |
new VueLoaderPlugin() | |
] | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const merge = require("webpack-merge"); | |
const common = require("./webpack.common.js"); | |
module.exports = merge(common, { | |
// devtool: "source-map", | |
// This stackoverflow was helpful for getting this setup | |
// https://stackoverflow.com/questions/57394214/django-webpack-how-to-serve-generated-webpack-bundles-with-webpack-dev-server | |
devServer: { | |
open: true, | |
host: "0.0.0.0", | |
port: 9090, | |
disableHostCheck: true, | |
// Note: in order to make inline reloading work you _must_ output a js bundle from webpack. If you try to use | |
// it only for css, and only output the css file, then webpack dev server can't add the bit of js it uses to force | |
// the browser to reload. | |
inline: true, | |
publicPath: "/static/bundles/", | |
proxy: { | |
"!/static/bundles/**": { | |
target: "http://localhost:8000", // points to django dev server | |
changeOrigin: true | |
} | |
} | |
}, | |
mode: "development" | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const merge = require("webpack-merge"); | |
const common = require("./webpack.common.js"); | |
module.exports = merge(common, { | |
devtool: "source-map", | |
mode: "production" | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment