- UI Revisions

This commit is contained in:
2018-05-29 00:30:49 -04:00
parent a7833a9314
commit 8f5ec53ac4
33 changed files with 487 additions and 447 deletions

View File

@@ -8,7 +8,7 @@ import { TabsPage } from '../pages/tabs/tabs';
@Component({
templateUrl: 'app.html'
})
export class Urge {
export class Urnings {
rootPage: any = TabsPage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {

View File

@@ -3,37 +3,39 @@ import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { IonicSwipeAllModule } from 'ionic-swipe-all';
import { Urge } from './app.component';
import { Urnings } from './app.component';
import { ChatPage } from '../pages/chat/chat';
import { CruisePage } from '../pages/cruise/cruise';
import { CruisesPage } from '../pages/cruises/cruises';
import { GridPage } from '../pages/grid/grid';
import { InformationPage } from '../pages/information/information';
import { LightboxPage } from '../pages/lightbox/lightbox';
import { MessagesPage } from '../pages/messages/messages';
import { ProfilePage } from '../pages/profile/profile';
import { TabsPage } from '../pages/tabs/tabs';
import { TellYourStoryPage } from '../pages/tell/tell';
import { UsersPage } from '../pages/users/users';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
@NgModule({
declarations: [
Urge,
Urnings,
ChatPage,
CruisePage,
CruisesPage,
InformationPage,
GridPage,
LightboxPage,
MessagesPage,
ProfilePage,
TabsPage
TabsPage,
TellYourStoryPage,
UsersPage
],
imports: [
BrowserModule,
HttpModule,
IonicSwipeAllModule,
IonicModule.forRoot(Urge, {
IonicModule.forRoot(Urnings, {
iconMode: 'ios',
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',
@@ -43,15 +45,16 @@ import { SplashScreen } from '@ionic-native/splash-screen';
],
bootstrap: [IonicApp],
entryComponents: [
Urge,
Urnings,
ChatPage,
CruisePage,
CruisesPage,
InformationPage,
GridPage,
LightboxPage,
MessagesPage,
ProfilePage,
TabsPage
TabsPage,
TellYourStoryPage,
UsersPage
],
providers: [
StatusBar,

View File

@@ -15,6 +15,10 @@
// for the .md, .ios, or .wp mode classes. The mode class is
// automatically applied to the <body> element in the app.
body {
font-family: 'PT Sans', sans-serif;
}
ion-toolbar {
color: #fff;
@@ -24,7 +28,7 @@ ion-toolbar {
.bar-button,
.toolbar-title {
color: #9e9ea8;
color: #ffffff;
}
}
@@ -59,7 +63,7 @@ ion-title {
.tab-button {
.tab-button-icon {
color: #9e9ea8;
color: #ffffff;
}
&[aria-selected=true] {

View File

@@ -2,7 +2,7 @@
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Urge</title>
<title>Urnings</title>
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
@@ -17,6 +17,7 @@
<link rel="apple-touch-startup-image" sizes="750x1334" href="assets/imgs/launch-screen-750x1334.png">
<link rel="apple-touch-startup-image" sizes="1125x2436" href="assets/imgs/launch-screen-1125x2436.png">
<link rel="apple-touch-startup-image" sizes="1242x2208" href="assets/imgs/launch-screen-1242x2208.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Urge">
@@ -33,6 +34,7 @@
}
</script>-->
<link href="https://fonts.googleapis.com/css?family=PT+Sans" rel="stylesheet">
<link href="build/main.css" rel="stylesheet">
</head>

View File

@@ -5,14 +5,7 @@
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
<ion-title><img class="title-profile-avatar" [src]="'https://appsby.fitz.guru/urge/' + this.profile.details.pic.thumb" height="24" width="24"> {{this.profile.details.name}}</ion-title>
<!--ion-buttons right>
<button ion-button icon-only>
<ion-icon name="more"></ion-icon>
</button>
</ion-buttons-->
</ion-toolbar>
</ion-header>

View File

@@ -12,40 +12,17 @@ page-chat {
.message-bubble {
background-color: #fdb315;
border-radius: 0.5rem;
font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif;
line-height: 1.5;
margin: 1rem 1rem 2.5rem auto;
max-width: 75%;
overflow: visible;
padding: 0.75rem;
position: relative;
&::after {
border: 0.625em solid transparent;
border-bottom: 0;
border-right: 0;
border-top-color: #fdb315;
bottom: 0;
content: '';
height: 0;
right: 2rem;
margin-bottom: -0.6em;
margin-left: -0.312em;
position: absolute;
width: 0;
}
&.is-user {
background-color: #6fbedf;
margin: 1rem auto 2.5rem 1rem;
&::after {
border: 0.625em solid transparent;
border-bottom: 0;
border-left: 0;
border-top-color: #6fbedf;
right: auto;
margin-right: -0.312em;
left: 2rem;
}
}
.item-inner {

View File

@@ -1,25 +0,0 @@
<ion-content no-padding [style.backgroundImage]="getBackground(this.cruise.pic)" (press)="showLightbox($event, this.cruise.pic.detail)">
<ion-toolbar>
<ion-buttons left>
<button ion-button icon-only (tap)="closeCruise($event)">
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
<div id="detail-overlay" class="details">
<ion-grid>
<ion-row nowrap align-items-center justify-content-between swipeAll (swipedown)="closeCruiseDetails($event)" (swipeup)="openCruiseDetails($event)" (click)="toggleCruiseDetails($event)">
<ion-col col-8>
<h2 class="placename">{{this.cruise.name}}</h2>
</ion-col>
</ion-row>
<ion-row class="location" *ngIf="this.cruise.location">
<ion-col col-4>Location</ion-col>
<ion-col col-8 [innerHTML]="getFormattedCruiseAddress(this.cruise.location)"></ion-col>
</ion-row>
<ion-row class="text" *ngIf="this.cruise.text">
<ion-col col-12 [innerHTML]="this.cruise.text"></ion-col>
</ion-row>
</ion-grid>
</div>
</ion-content>

View File

@@ -1,47 +0,0 @@
page-cruise {
ion-content {
background-position: center;
background-repeat: no-repeat;
background-size: contain;
}
.scroll-content {
overflow-y: hidden;
}
ion-toolbar {
.toolbar-background {
background-color: transparent;
}
.bar-button {
color: #ffffff;
}
}
.details {
background: rgba(0, 0, 0, 0.8);
bottom: 0;
height: 60px;
left: 0;
position: absolute;
right: 0;
transition: all 250ms 125ms ease-in-out;
h2 {
margin: 0;
}
.location {
margin-top: 1.5rem;
}
&.open {
height: 100%;
overflow-y: scroll;
padding-top: 35px;
}
}
}

View File

@@ -1,80 +0,0 @@
import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController, NavParams } from 'ionic-angular';
import { LightboxPage } from '../lightbox/lightbox';
@Component({
selector: 'page-cruise',
templateUrl: 'cruise.html'
})
export class CruisePage {
detailsOpen: boolean = false;
cruise: any;
tabNavEl: any;
constructor(public navCtrl: NavController, public navParams: NavParams, private _sanitizer: DomSanitizer) {
this.cruise = navParams.get('cruise');
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'none';
}
closeCruise(event) {
this.navCtrl.pop();
}
closeCruiseDetails(event) {
if (this.detailsOpen) {
this.detailsOpen = false;
document.getElementById('detail-overlay').classList.remove('open');
}
}
getBackground(images) {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + images.detail + ')');
}
getFormattedCruiseAddress(location) {
var address = '';
if (location && location.address) {
address += location.address.street1 ? location.address.street1 + '<br>' : '';
address += location.address.street2 ? location.address.street2 + '<br>' : '';
address += location.address.locality ? location.address.locality + ', ' : '';
address += location.address.region ? location.address.region + ' ' : '';
address += location.address.postal ? location.address.postal + '<br>' : '';
address += location.address.country ? location.address.country : '';
}
return address;
}
markFavorite(event, cruise) {
console.debug('favorite cruise', { event: event, profile: cruise });
}
openCruiseDetails(event) {
if (!this.detailsOpen) {
this.detailsOpen = true;
document.getElementById('detail-overlay').classList.add('open');
}
}
showLightbox(event, image) {
if (event.target.classList.contains('scroll-content')) {
this.navCtrl.push(LightboxPage, {
image: image
});
}
}
toggleCruiseDetails(event) {
if (!this.detailsOpen) {
this.openCruiseDetails(event);
} else {
this.closeCruiseDetails(event);
}
}
}

View File

@@ -1,9 +0,0 @@
<ion-content no-padding>
<ion-grid no-padding>
<ion-row align-items-stretch>
<ion-col col-6 class="cruise" *ngFor="let current of cruises" (tap)="profileTapped($event, current)" [style.backgroundImage]="getBackgroundThumbnail(current.pic)">
<span class="placename" [ngClass]="{ 'online': (current.messages?.length > 0) }">{{current.name}}</span>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

View File

@@ -1,38 +0,0 @@
import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController } from 'ionic-angular';
import { CruiseService } from '../../services/cruises';
import { CruisePage } from '../cruise/cruise';
@Component({
selector: 'page-cruises',
templateUrl: 'cruises.html',
providers: [ CruiseService ]
})
export class CruisesPage {
cruises: any;
tabNavEl: any;
constructor(public navCtrl: NavController, public cruiseService: CruiseService, private _sanitizer: DomSanitizer) {
cruiseService.load().then((data) => {
this.cruises = data;
});
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'flex';
}
getBackgroundThumbnail(images) {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + images.thumb + ')');
}
profileTapped(event, cruise) {
this.navCtrl.push(CruisePage, {
cruise: cruise
});
}
}

View File

@@ -1,3 +1,9 @@
<ion-header>
<ion-toolbar>
<ion-title>Urnings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content no-padding>
<ion-grid no-padding>
<ion-row align-items-stretch>

View File

@@ -1,6 +1,21 @@
page-grid {
ion-col {
ion-toolbar {
.toolbar-title {
color: #ffffff;
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
text-decoration: underline;
}
}
.grid {
.row {
.col {
&.profile {
background-size: cover;
@@ -13,14 +28,14 @@ page-grid {
background-size: cover;
bottom: 0.25rem;
box-sizing: border-box;
color: #acacac;
color: #ffffff;
display: inline-block;
left: 0.5rem;
overflow: hidden;
position: absolute;
right: 0.25rem;
text-overflow: ellipsis;
text-shadow: rgba(0, 0, 0, 1);
text-shadow: 0 0 3px rgba(0, 0, 0, 1);
white-space: nowrap;
&::before {
@@ -39,8 +54,10 @@ page-grid {
&.online {
&::before {
background-color: #00FF00;
border-color: #00FF00;
background-color: #00ff00;
border-color: #00ff00;
}
}
}
}
}

View File

@@ -5,6 +5,7 @@ import { NavController } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile';
import { TellYourStoryPage } from '../tell/tell';
@Component({
selector: 'page-grid',
@@ -27,6 +28,10 @@ export class GridPage {
this.tabNavEl.style.display = 'flex';
}
doTellStory() {
this.navCtrl.push(TellYourStoryPage);
}
getBackgroundThumbnail(pics) {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + pics.thumb + ')');
}
@@ -41,7 +46,7 @@ export class GridPage {
profileTapped(event, profile) {
this.navCtrl.push(ProfilePage, {
profile: profile
profile: profile,
});
}
}

View File

@@ -0,0 +1,20 @@
<ion-header>
<ion-toolbar>
<ion-buttons right>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content padding>
<div class="content-box" padding margin>
<h3>About this Project</h3>
<div class="info-blurb">
<p>The app was designed by Nicholas Pfosi and developed by Michael Fitzpatrick, modeled after the popular gay dating app Grindr.</p>
<p>Presenting these stories in this form, which is the conduit through which much participation in dating occurs, served multiple purposes. First, it educated the viewer who may not have used Grindr before, how it functions and how it is different from other apps such as Tinder, whereby matching with a person is a prerequisite for conversation. Second, it makes the scope of the project flexible, allowing for the submission of stories from the audience to be slotted into an expandable presentation.</p>
<p>Please direct any questions or concerns to Nicholas Pfosi at npfosi@gmail.com</p>
</div>
</div>
</ion-content>

View File

@@ -0,0 +1,9 @@
page-information {
.content-box {
background-color: #ffffff;
color: #000000;
font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif;
line-height: 1.5;
}
}

View File

@@ -0,0 +1,23 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-information',
templateUrl: 'information.html',
})
export class InformationPage {
tabNavEl: any;
constructor(public navCtrl: NavController) {
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'none';
}
close(event) {
this.navCtrl.pop();
}
}

View File

@@ -1,8 +1,8 @@
<ion-header>
<ion-toolbar>
<ion-buttons left>
<ion-buttons right>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="arrow-back"></ion-icon>
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>

View File

@@ -1,23 +1,14 @@
<ion-header no-border>
<ion-row>
<ion-col text-center>
<button ion-button clear small>
Messages
</button>
</ion-col>
<!--ion-col text-center>
<button ion-button clear small>
Taps
</button>
</ion-col-->
</ion-row>
<ion-header>
<ion-toolbar>
<ion-title>Urnings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content no-padding>
<ion-list>
<ng-container *ngFor="let profile of profiles">
<ion-item no-padding *ngIf="profile.messages?.length > 0">
<ion-thumbnail item-start (tap)="profilePictureTapped($event, profile)">
<ion-thumbnail padding-left item-start (tap)="profilePictureTapped($event, profile)">
<img [src]="'https://appsby.fitz.guru/urge/' + profile.details.pic.thumb">
</ion-thumbnail>
<ion-grid (tap)="interviewTapped($event, profile)">

View File

@@ -1,5 +1,16 @@
page-messages {
ion-toolbar {
.toolbar-title {
color: #ffffff;
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
text-decoration: underline;
}
}
ion-header {
.button {
@@ -8,10 +19,12 @@ page-messages {
}
.col {
color: #acacac;
color: #ffffff;
font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif;
line-height: 1.5;
&.username {
font-size: 0.8em;
font-weight: 700;
}
&.timestamp {
@@ -19,6 +32,10 @@ page-messages {
font-style: italic;
text-align: right;
}
.latest-message {
font-size: 0.8em;
}
}
.list {

View File

@@ -1,81 +1,27 @@
<ion-content no-padding [style.backgroundImage]="getBackground(profile.details.pic)" (press)="showLightbox($event, profile.details.pic.detail)">
<ion-toolbar>
<ion-content no-padding [style.backgroundImage]="getBackground(profile.details.pic)" (press)="showLightbox($event, profile.details.pic.detail)" on-swipe-left="nextProfile($event)" on-swipe-right="previousProfile($event)">
<ion-toolbar class="profile-toolbar">
<ion-buttons left>
<button ion-button icon-only (tap)="closeProfile($event)">
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
<!--ion-buttons right>
<button ion-button icon-only>
<ion-icon name="cog"></ion-icon>
</button>
</ion-buttons-->
<ion-title>{{this.profile.details.name}}</ion-title>
</ion-toolbar>
<button ion-button icon-only clear large (tap)="openChat($event, this.profile)" class="button-chat">
<ion-icon name="ios-chatboxes"></ion-icon>
</button>
<div id="detail-overlay" class="details">
<ion-grid>
<ion-row nowrap align-items-center justify-content-between swipeAll (swipedown)="closeProfileDetails($event)" (swipeup)="openProfileDetails($event)" (click)="toggleProfileDetails($event)">
<ion-col col-8>
<h2 class="display-name">{{this.profile.details.name}}</h2>
</ion-col>
<ion-col col-4 class="actions" *ngIf="this.profile.messages?.length > 0">
<button ion-button icon-only clear (tap)="openChat($event, this.profile)">
<ion-icon name='ios-chatboxes-outline'></ion-icon>
</button>
<ion-row nowrap align-items-center justify-content-between>
<ion-col col-12 text-center (click)="toggleProfileDetails($event)" class="detail-toggle">
<ion-icon name="arrow-down"></ion-icon>
</ion-col>
</ion-row>
<ion-row class="about" *ngIf="this.profile.details.about">
<ion-col col-12 [innerHTML]="this.profile.details.about"></ion-col>
</ion-row>
<ion-row class="height" *ngIf="this.profile.details.height">
<ion-col col-4>Height</ion-col>
<ion-col col-8>{{this.profile.details.height}}</ion-col>
</ion-row>
<ion-row class="weight" *ngIf="this.profile.details.weight">
<ion-col col-4>Weight</ion-col>
<ion-col col-8>{{this.profile.details.weight}}</ion-col>
</ion-row>
<ion-row class="ethnicity" *ngIf="this.profile.details.ethnicity != 'dns'">
<ion-col col-4>Ethnicity</ion-col>
<ion-col col-8>{{this.profile.details.ethnicity}}</ion-col>
</ion-row>
<ion-row class="body" *ngIf="this.profile.details.body != 'dns'">
<ion-col col-4>Body Type</ion-col>
<ion-col col-8>{{this.profile.details.body}}</ion-col>
</ion-row>
<ion-row class="gender" *ngIf="this.profile.details.gender">
<ion-col col-4>Gender</ion-col>
<ion-col col-8>{{this.profile.details.gender}}</ion-col>
</ion-row>
<ion-row class="pronouns" *ngIf="this.profile.details.pronouns">
<ion-col col-4>Pronouns</ion-col>
<ion-col col-8>{{this.profile.details.pronouns}}</ion-col>
</ion-row>
<ion-row class="tribes" *ngIf="this.profile.details.tribe?.length > 0">
<ion-col col-4>Tribes</ion-col>
<ion-col col-8><span *ng>{{this.profile.details.tribe}}</span></ion-col>
</ion-row>
<ion-row class="position" *ngIf="this.profile.details.position != 'dns'">
<ion-col col-4>Position</ion-col>
<ion-col col-8>{{this.profile.details.position}}</ion-col>
</ion-row>
<ion-row class="relationship" *ngIf="this.profile.details.relationship != 'dns'">
<ion-col col-4>Relationship</ion-col>
<ion-col col-8>{{this.profile.details.relationship}}</ion-col>
</ion-row>
<ion-row class="looking" *ngIf="this.profile.details.looking?.length > 0">
<ion-col col-4>I'm Looking For</ion-col>
<ion-col col-8><span *ng>{{this.profile.details.looking}}</span></ion-col>
</ion-row>
<ion-row class="status" *ngIf="this.profile.details.status != 'dns'">
<ion-col col-4>HIV Status</ion-col>
<ion-col col-8>{{this.profile.details.status}}</ion-col>
</ion-row>
<ion-row class="tested" *ngIf="this.profile.details.tested">
<ion-col col-4>Last Tested</ion-col>
<ion-col col-8>{{this.profile.details.tested}}</ion-col>
</ion-row>
</ion-grid>
</div>
</ion-content>

View File

@@ -11,18 +11,38 @@ page-profile {
}
ion-toolbar {
border-bottom: 1px solid #ffffff;
transition: opacity 250ms 125ms ease-in-out;
.toolbar-background {
background-color: transparent;
&.hidden {
opacity: 0;
z-index: -1;
}
.bar-button {
.toolbar-background {
background-color: rgba(0, 0, 0, 1);
}
.bar-button,
.toolbar-title {
color: #ffffff;
}
}
.button-chat {
bottom: 3rem;
color: #fdb315;
position: absolute;
right: 1.5rem;
z-index: 100;
}
.detail-toggle {
font-size: 2.5em;
z-index: 100;
}
.details {
background: rgba(0, 0, 0, 0.8);
bottom: 0;
height: 60px;
left: 0;
@@ -30,14 +50,15 @@ page-profile {
right: 0;
transition: all 250ms 125ms ease-in-out;
h2 {
margin: 0;
}
&.open {
background: rgba(0, 0, 0, 0.8);
height: 100%;
overflow-y: scroll;
padding-top: 35px;
}
.about {
font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif;
line-height: 1.5;
}
.actions {

View File

@@ -4,18 +4,21 @@ import { NavController, NavParams } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { LightboxPage } from '../lightbox/lightbox';
import { ProfileService } from '../../services/profiles';
@Component({
selector: 'page-profile',
templateUrl: 'profile.html'
templateUrl: 'profile.html',
providers: [ ProfileService ]
})
export class ProfilePage {
detailsOpen: boolean = false;
profile: any;
tabNavEl: any;
constructor(public navCtrl: NavController, public navParams: NavParams, private _sanitizer: DomSanitizer) {
constructor(public navCtrl: NavController, public navParams: NavParams, public profileService: ProfileService, private _sanitizer: DomSanitizer) {
this.profile = navParams.get('profile');
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
@@ -31,6 +34,7 @@ export class ProfilePage {
closeProfileDetails(event) {
if (this.detailsOpen) {
this.detailsOpen = false;
document.querySelector('.profile-toolbar').classList.remove('hidden');
document.getElementById('detail-overlay').classList.remove('open');
}
}
@@ -43,6 +47,11 @@ export class ProfilePage {
console.debug('favorite profile', { event: event, profile: profile });
}
nextProfile(event) {
this.profile = this.profileService.getNextProfile(this.profile._id);
this.navCtrl.setRoot(this.navCtrl.getActive().component);
}
openChat(event, profile) {
this.navCtrl.push(ChatPage, {
profile: profile
@@ -52,10 +61,16 @@ export class ProfilePage {
openProfileDetails(event) {
if (!this.detailsOpen) {
this.detailsOpen = true;
document.querySelector('.profile-toolbar').classList.add('hidden');
document.getElementById('detail-overlay').classList.add('open');
}
}
previousProfile(event) {
this.profile = this.profileService.getPreviousProfile(this.profile._id);
this.navCtrl.setRoot(this.navCtrl.getActive().component);
}
showLightbox(event, image) {
if (event.target.classList.contains('scroll-content')) {
this.navCtrl.push(LightboxPage, {

View File

@@ -1,5 +1,6 @@
<ion-tabs id="tab-nav" selectedIndex="0">
<ion-tab [root]="tab1Root" tabIcon="contacts"></ion-tab>
<ion-tab [root]="tab2Root" tabIcon="boat"></ion-tab>
<ion-tab [root]="tab2Root" tabIcon="compass"></ion-tab>
<ion-tab [root]="tab3Root" tabIcon="chatboxes"></ion-tab>
<ion-tab [root]="tab4Root" tabIcon="information-circle"></ion-tab>
</ion-tabs>

View File

@@ -1,8 +1,9 @@
import { Component } from '@angular/core';
import { GridPage } from '../grid/grid';
import { CruisesPage } from '../cruises/cruises';
import { InformationPage } from '../information/information';
import { MessagesPage } from '../messages/messages';
import { UsersPage } from '../users/users';
@Component({
templateUrl: 'tabs.html'
@@ -10,8 +11,9 @@ import { MessagesPage } from '../messages/messages';
export class TabsPage {
tab1Root = GridPage;
tab2Root = CruisesPage;
tab2Root = UsersPage;
tab3Root = MessagesPage;
tab4Root = InformationPage;
constructor() {

12
src/pages/tell/tell.html Normal file
View File

@@ -0,0 +1,12 @@
<ion-header>
<ion-toolbar>
<ion-buttons right>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
</ion-content>

View File

@@ -1,4 +1,4 @@
page-cruises {
page-tell-your-story {
ion-col {

26
src/pages/tell/tell.ts Normal file
View File

@@ -0,0 +1,26 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ProfileService } from '../../services/profiles';
@Component({
selector: 'page-tell-your-story',
templateUrl: 'tell.html',
providers: [ ProfileService ]
})
export class TellYourStoryPage {
tabNavEl: any;
constructor(public navCtrl: NavController) {
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'none';
}
close(event) {
this.navCtrl.pop();
}
}

View File

@@ -0,0 +1,20 @@
<ion-header>
<ion-toolbar>
<ion-title>Urnings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content no-padding>
<ion-grid no-padding>
<ion-row align-items-stretch>
<ion-col col-4 class="profile tell-your-story">
<button ion-button clear large icon-only (tap)="doTellStory()">
<ion-icon name="md-person-add"></ion-icon>
</button>
</ion-col>
<ion-col col-4 class="profile" *ngFor="let current of profiles" (tap)="profileTapped($event, current)" (press)="profilePressed($event, current)" [style.backgroundImage]="getBackgroundThumbnail(current.details.pic)">
<span class="username" [ngClass]="{ 'online': (current.messages?.length > 0) }">{{current.details.name}}</span>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

View File

@@ -0,0 +1,78 @@
page-users {
ion-toolbar {
.toolbar-title {
color: #ffffff;
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
text-decoration: underline;
}
}
.grid {
.row {
.col {
&.profile {
background-size: cover;
border: 1px solid #000000;
box-sizing: border-box;
padding: 0 0 33% !important;
position: relative;
&.tell-your-story {
position: relative;
button {
color: #acacac;
position: absolute;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
}
}
.username {
background-size: cover;
bottom: 0.25rem;
box-sizing: border-box;
color: #ffffff;
display: inline-block;
left: 0.5rem;
overflow: hidden;
position: absolute;
right: 0.25rem;
text-overflow: ellipsis;
text-shadow: 0 0 3px rgba(0, 0, 0, 1);
white-space: nowrap;
&::before {
border: 0.125rem solid #acacac;
border-radius: 1rem;
bottom: 0.125rem;
content: '';
display: inline-block;
height: 0.8rem;
margin-right: 0.5rem;
position: relative;
vertical-align: middle;
width: 0.8rem;
}
&.online {
&::before {
background-color: #00ff00;
border-color: #00ff00;
}
}
}
}
}
}
}
}

52
src/pages/users/users.ts Normal file
View File

@@ -0,0 +1,52 @@
import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile';
import { TellYourStoryPage } from '../tell/tell';
@Component({
selector: 'page-users',
templateUrl: 'users.html',
providers: [ ProfileService ]
})
export class UsersPage {
profiles: any;
tabNavEl: any;
constructor(public navCtrl: NavController, public profileService: ProfileService, private _sanitizer: DomSanitizer) {
profileService.loadSubmitted().then((data) => {
this.profiles = data;
});
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'flex';
}
doTellStory() {
this.navCtrl.push(TellYourStoryPage);
}
getBackgroundThumbnail(pics) {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + pics.thumb + ')');
}
profilePressed(event, profile) {
if (profile.messages && profile.messages.length) {
this.navCtrl.push(ChatPage, {
profile: profile
});
}
}
profileTapped(event, profile) {
this.navCtrl.push(ProfilePage, {
profile: profile,
});
}
}

View File

@@ -1,44 +0,0 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class CruiseService {
endpoint: string = 'assets/data/cruises.json';
//endpoint: string = 'https://api.fitz.guru/urge/cruises';
idMap: any;
cruises: any;
constructor(private http: Http) {
this.idMap = {};
this.cruises = null;
}
load() {
if (this.cruises) {
return Promise.resolve(this.cruises);
}
return new Promise(resolve => {
this.http.get(this.endpoint)
.map(res => res.json())
.subscribe(data => {
this.cruises = data;
this.cruises.reduce((map, cruise, i) => {
map[cruise._id] = i;
return map;
}, this.idMap);
resolve(this.cruises);
});
});
}
getCruises() {
return this.cruises;
}
getCruiseById(id) {
return this.cruises[this.idMap[id]];
}
}

View File

@@ -5,11 +5,14 @@ import 'rxjs/add/operator/map';
@Injectable()
export class ProfileService {
endpoint: string = 'https://api.fitz.guru/urge/profiles';
endpoint: string = 'https://api.fitz.guru/urnings/profiles';
fallback: string = 'assets/data/profiles.json';
idMap: any;
epSubmitted: string = '/submitted';
epVerified: string = '/verified';
idMap: any = { all: {}, submitted: {}, verified: {} };
profiles: any;
constructor(private http: Http) {
this.idMap = {};
this.profiles = null;
@@ -21,27 +24,59 @@ export class ProfileService {
}
return new Promise(resolve => {
this.http.get(this.endpoint)
this.doGetRequest(this.endpoint, resolve);
});
}
loadSubmitted() {
if (this.profiles) {
return Promise.resolve(this.profiles);
}
return new Promise(resolve => {
this.doGetRequest(this.endpoint + this.epSubmitted, resolve, 'submitted');
});
}
loadVerified() {
if (this.profiles) {
return Promise.resolve(this.profiles);
}
return new Promise(resolve => {
this.doGetRequest(this.endpoint + this.epVerified, resolve, 'verified');
});
}
doGetRequest(endpoint, resolve, type = 'all') {
this.http.get(endpoint)
.map(res => res.json())
.subscribe(
data => {
this.profiles = data;
this.profiles = {};
this.profiles[type] = data;
this.profiles.reduce((map, profile, i) => {
map[profile._id] = i;
return map;
}, this.idMap);
resolve(this.profiles);
}, this.idMap[type]);
resolve(this.profiles[type]);
},
error => {
this.profiles = this.fallback;
this.profiles.reduce((map, profile, i) => {
map[profile._id] = i;
return map;
}, this.idMap);
resolve(this.profiles);
this.doGetRequest(this.fallback, resolve);
}
);
});
)
}
getNextProfile(id, type) {
var nextIdIndex = this.idMap[id] + 1;
nextIdIndex = nextIdIndex >= this.profiles.length ? 0 : nextIdIndex;
return this.profiles[nextIdIndex];
}
getPreviousProfile(id, type) {
var prevIdIndex = this.idMap[id] + 1;
prevIdIndex = prevIdIndex < 0 ? (this.profiles.length - 1) : prevIdIndex;
return this.profiles[prevIdIndex];
}
getProfiles() {
@@ -51,4 +86,12 @@ export class ProfileService {
getProfileById(id) {
return this.profiles[this.idMap[id]];
}
getSubmittedProfiles() {
}
getVerifiedProfiles() {
}
}