Initial commit

This commit is contained in:
2018-03-02 02:59:55 -05:00
parent 30518e56d4
commit 33cf657c70
34 changed files with 541 additions and 124 deletions

View File

@@ -25,6 +25,7 @@
"@ionic-native/status-bar": "4.4.0",
"@ionic/storage": "2.1.3",
"ionic-angular": "3.9.2",
"ionic-swipe-all": "^1.2.0",
"ionicons": "3.0.0",
"rxjs": "5.5.2",
"sw-toolbox": "3.6.0",

View File

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

View File

@@ -1,11 +1,15 @@
import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { IonicSwipeAllModule } from 'ionic-swipe-all';
import { Groundr } from './app.component';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { ChatPage } from '../pages/chat/chat';
import { GridPage } from '../pages/grid/grid';
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 { StatusBar } from '@ionic-native/status-bar';
@@ -13,22 +17,34 @@ import { SplashScreen } from '@ionic-native/splash-screen';
@NgModule({
declarations: [
MyApp,
AboutPage,
ContactPage,
HomePage,
Groundr,
ChatPage,
GridPage,
LightboxPage,
MessagesPage,
ProfilePage,
TabsPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
HttpModule,
IonicSwipeAllModule,
IonicModule.forRoot(Groundr, {
iconMode: 'ios',
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',
tabsPlacement: 'bottom',
pageTransition: 'ios-transition'
})
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
AboutPage,
ContactPage,
HomePage,
Groundr,
ChatPage,
GridPage,
LightboxPage,
MessagesPage,
ProfilePage,
TabsPage
],
providers: [

View File

@@ -14,3 +14,54 @@
// To declare rules for a specific mode, create a child rule
// for the .md, .ios, or .wp mode classes. The mode class is
// automatically applied to the <body> element in the app.
ion-toolbar {
color: #fff;
.toolbar-background {
background-color: #000000;
}
}
ion-title {
text-align: center;
}
.content {
background-color: #191b1c;
color: #fff;
}
.item {
background-color: #1d1e1f;
color: #fff;
}
.list {
.item-block .item-inner {
border-bottom-color: #333435;
}
}
.tabs {
.tabbar {
background-color: #090a0a;
}
.tab-button {
.tab-button-icon {
color: #9e9ea8;
}
&[aria-selected=true] {
.tab-button-icon {
color: #fdb315;
}
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Ionic App</title>
<title>Groundr</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">

View File

@@ -1,6 +1,6 @@
{
"name": "Ionic",
"short_name": "Ionic",
"name": "Groundr",
"short_name": "Groundr",
"start_url": "index.html",
"display": "standalone",
"icons": [{
@@ -10,4 +10,4 @@
}],
"background_color": "#4e8ef7",
"theme_color": "#4e8ef7"
}
}

View File

@@ -1,11 +0,0 @@
<ion-header>
<ion-navbar>
<ion-title>
About
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
</ion-content>

View File

@@ -1,3 +0,0 @@
page-about {
}

View File

@@ -1,14 +0,0 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
constructor(public navCtrl: NavController) {
}
}

32
src/pages/chat/chat.html Normal file
View File

@@ -0,0 +1,32 @@
<ion-header>
<ion-toolbar>
<ion-buttons left>
<button ion-button icon-only (tap)="closeChat($event)">
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
<ion-title><img [src]="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>
<ion-content>
<ion-list>
<ion-item class="message-bubble" *ngFor="let message of this.profile.messages" [ngClass]="{ 'user': (message.isUser == true) }">
<img *ngIf="message.image" [src]="message.image" (press)="showLightbox($event, message.image)">
<p *ngIf="message.text != ''">{{message.text}}</p>
</ion-item>
</ion-list>
</ion-content>
<ion-footer>
<ion-toolbar>
</ion-toolbar>
</ion-footer>

3
src/pages/chat/chat.scss Normal file
View File

@@ -0,0 +1,3 @@
page-chat {
}

28
src/pages/chat/chat.ts Normal file
View File

@@ -0,0 +1,28 @@
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { LightboxPage } from '../lightbox/lightbox';
@Component({
selector: 'page-chat',
templateUrl: 'chat.html'
})
export class ChatPage {
profile: any;
constructor(public navCtrl: NavController, private navParams: NavParams) {
this.profile = navParams.get('profile');
}
closeChat(event) {
this.navCtrl.pop();
}
showLightbox(event, image) {
this.navCtrl.push(LightboxPage, {
image: image
});
}
}

View File

@@ -1,17 +0,0 @@
<ion-header>
<ion-navbar>
<ion-title>
Contact
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>Follow us on Twitter</ion-list-header>
<ion-item>
<ion-icon name="ionic" item-start></ion-icon>
@ionicframework
</ion-item>
</ion-list>
</ion-content>

View File

@@ -1,3 +0,0 @@
page-contact {
}

View File

@@ -1,14 +0,0 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-contact',
templateUrl: 'contact.html'
})
export class ContactPage {
constructor(public navCtrl: NavController) {
}
}

9
src/pages/grid/grid.html Normal file
View File

@@ -0,0 +1,9 @@
<ion-content no-padding>
<ion-grid no-padding>
<ion-row align-items-stretch>
<ion-col col-4 *ngFor="let current of profiles" (tap)="profileTapped($event, current)">
<img [src]="current.details.pic.thumb">
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

7
src/pages/grid/grid.scss Normal file
View File

@@ -0,0 +1,7 @@
page-grid {
ion-col {
box-sizing: border-box;
border: 1px solid #000000;
}
}

27
src/pages/grid/grid.ts Normal file
View File

@@ -0,0 +1,27 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile';
@Component({
selector: 'page-grid',
templateUrl: 'grid.html',
providers: [ ProfileService ]
})
export class GridPage {
profiles: any;
constructor(public navCtrl: NavController, public profileService: ProfileService) {
profileService.load().then((data) => {
this.profiles = data;
});
}
profileTapped(event, profile) {
this.navCtrl.push(ProfilePage, {
profile: profile
});
}
}

View File

@@ -1,17 +0,0 @@
<ion-header>
<ion-navbar>
<ion-title>Home</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Welcome to Ionic!</h2>
<p>
This starter project comes with simple tabs-based layout for apps
that are going to primarily use a Tabbed UI.
</p>
<p>
Take a look at the <code>src/pages/</code> directory to add or change tabs,
update any existing page or create new pages.
</p>
</ion-content>

View File

@@ -1,3 +0,0 @@
page-home {
}

View File

@@ -1,14 +0,0 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController) {
}
}

View File

@@ -0,0 +1,13 @@
<ion-header>
<ion-toolbar>
<ion-buttons left>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content (click)="close($event)">
<img [src]="this.image">
</ion-content>

View File

@@ -0,0 +1,3 @@
page-lightbox {
}

View File

@@ -0,0 +1,20 @@
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
@Component({
selector: 'page-lightbox',
templateUrl: 'lightbox.html'
})
export class LightboxPage {
image: string;
constructor(public navCtrl: NavController, private navParams: NavParams) {
this.image = navParams.get('image');
}
close(event) {
this.navCtrl.pop();
}
}

View File

@@ -0,0 +1,37 @@
<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-content no-padding>
<ion-list>
<ion-item no-padding *ngFor="let profile of profiles">
<ion-thumbnail item-start (tap)="profilePictureTapped($event, profile)">
<img [src]="profile.details.pic.thumb">
</ion-thumbnail>
<ion-grid (tap)="interviewTapped($event, profile)">
<ion-row nowrap justify-content-between>
<ion-col>
{{profile.details.name}}
</ion-col>
<ion-col>
23h ago
</ion-col>
</ion-row>
<ion-row nowrap>
<ion-col [innerHTML]="getLatestMessage(profile.messages)"></ion-col>
</ion-row>
</ion-grid>
</ion-item>
</ion-list>
</ion-content>

View File

@@ -0,0 +1,3 @@
page-messages {
}

View File

@@ -0,0 +1,39 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile';
import { ChatPage } from '../chat/chat';
@Component({
selector: 'page-messages',
templateUrl: 'messages.html',
providers: [ ProfileService ]
})
export class MessagesPage {
profiles: any;
constructor(public navCtrl: NavController, public profileService: ProfileService) {
profileService.load().then((data) => {
this.profiles = data;
});
}
getLatestMessage(messages) {
var latest = Math.max.apply(Math, messages.map(function(o){ return o.order; }));
return messages[latest].text != '' ? messages[latest].text : '<em>Picture</em>';
}
interviewTapped(event, profile) {
this.navCtrl.push(ChatPage, {
profile: profile
});
}
profilePictureTapped(event, profile) {
this.navCtrl.push(ProfilePage, {
profile: profile
});
}
}

View File

@@ -0,0 +1,77 @@
<ion-content no-padding [style.backgroundImage]="getBackground(profile.details.pic)" (tap)="showLightbox($event, profile.details.pic.detail)">
<ion-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-toolbar>
<div id="detail-overlay" class="details" swipeAll (swipedown)="closeProfileDetails($event)" (swipeup)="openProfileDetails($event)">
<ion-grid>
<ion-row nowrap align-items-center justify-content-between>
<ion-col col-8>
<h2>{{this.profile.details.name}}</h2>
</ion-col>
<ion-col col-4 class="actions">
<button ion-button icon-only clear (tap)="openChat($event, this.profile)">
<ion-icon name='ios-chatboxes-outline'></ion-icon>
</button>
</ion-col>
</ion-row>
<ion-row *ngIf="this.profile.details.about">
<ion-col col-12>{{this.profile.details.about}}</ion-col>
</ion-row>
<ion-row *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 *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 *ngIf="this.profile.details.ethnicity">
<ion-col col-4>Ethnicity</ion-col>
<ion-col col-8>{{this.profile.details.ethnicity}}</ion-col>
</ion-row>
<ion-row *ngIf="this.profile.details.body">
<ion-col col-4>Body Type</ion-col>
<ion-col col-8>{{this.profile.details.body}}</ion-col>
</ion-row>
<ion-row *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 *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 *ngIf="this.profile.details.tribe">
<ion-col col-4>Tribes</ion-col>
<ion-col col-8>{{this.profile.details.tribe}}</ion-col>
</ion-row>
<ion-row *ngIf="this.profile.details.position">
<ion-col col-4>Position</ion-col>
<ion-col col-8>{{this.profile.details.position}}</ion-col>
</ion-row>
<ion-row *ngIf="this.profile.details.looking">
<ion-col col-4>I'm Looking For</ion-col>
<ion-col col-8>{{this.profile.details.looking}}</ion-col>
</ion-row>
<ion-row *ngIf="this.profile.details.status">
<ion-col col-4>HIV Status</ion-col>
<ion-col col-8>{{this.profile.details.status}}</ion-col>
</ion-row>
<ion-row *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

@@ -0,0 +1,46 @@
page-profile {
ion-content {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
ion-toolbar {
.toolbar-background {
background-color: transparent;
}
.bar-button {
color: #ffffff;
}
}
.details {
background: rgba(0, 0, 0, 0.8);
bottom: 0;
height: 75px;
left: 0;
position: absolute;
right: 0;
transition: all 250ms 125ms ease-in-out;
h2 {
margin: 0;
}
&.open {
height: 100%;
padding-top: 35px;
}
.actions {
text-align: right;
.button-clear {
color: #fdb315;
}
}
}
}

View File

@@ -0,0 +1,60 @@
import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController, NavParams } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { LightboxPage } from '../lightbox/lightbox';
@Component({
selector: 'page-profile',
templateUrl: 'profile.html'
})
export class ProfilePage {
detailsOpen: boolean = false;
profile: any;
constructor(public navCtrl: NavController, public navParams: NavParams, private _sanitizer: DomSanitizer) {
this.profile = navParams.get('profile');
}
closeProfile(event) {
this.navCtrl.pop();
}
closeProfileDetails(event) {
if (this.detailsOpen) {
this.detailsOpen = false;
document.getElementById('detail-overlay').classList.remove('open');
}
}
getBackground(pics) {
return this._sanitizer.bypassSecurityTrustStyle('url(' + pics.detail + ')');
}
markFavorite(event, profile) {
console.debug('favorite profile', { event: event, profile: profile });
}
openChat(event, profile) {
this.navCtrl.push(ChatPage, {
profile: profile
});
}
openProfileDetails(event) {
if (!this.detailsOpen) {
this.detailsOpen = true;
document.getElementById('detail-overlay').classList.add('open');
}
}
showLightbox(event, image) {
if (event.target.classList.contains('content')) {
this.navCtrl.push(LightboxPage, {
image: image
});
}
}
}

View File

@@ -1,5 +1,5 @@
<ion-tabs>
<ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabTitle="About" tabIcon="information-circle"></ion-tab>
<ion-tab [root]="tab3Root" tabTitle="Contact" tabIcon="contacts"></ion-tab>
<ion-tabs selectedIndex="1">
<!--ion-tab [root]="tab1Root" tabIcon="star"></ion-tab-->
<ion-tab [root]="tab1Root" tabIcon="contacts"></ion-tab>
<ion-tab [root]="tab2Root" tabIcon="chatboxes"></ion-tab>
</ion-tabs>

View File

@@ -1,17 +1,15 @@
import { Component } from '@angular/core';
import { AboutPage } from '../about/about';
import { ContactPage } from '../contact/contact';
import { HomePage } from '../home/home';
import { GridPage } from '../grid/grid';
import { MessagesPage } from '../messages/messages';
@Component({
templateUrl: 'tabs.html'
})
export class TabsPage {
tab1Root = HomePage;
tab2Root = AboutPage;
tab3Root = ContactPage;
tab1Root = GridPage;
tab2Root = MessagesPage;
constructor() {

42
src/services/profiles.ts Normal file
View File

@@ -0,0 +1,42 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class ProfileService {
idMap: any;
profiles: any;
constructor(private http: Http) {
this.idMap = {};
this.profiles = null;
}
load() {
if (this.profiles) {
return Promise.resolve(this.profiles);
}
return new Promise(resolve => {
this.http.get('/assets/data/profiles.json')
.map(res => res.json())
.subscribe(data => {
this.profiles = data;
this.profiles.reduce((map, profile, i) => {
map[profile._id] = i;
return map;
}, this.idMap);
resolve(this.profiles);
});
});
}
getProfiles() {
return this.profiles;
}
getProfileById(id) {
return this.profiles[this.idMap[id]];
}
}