浏览代码

Calendar UI

master
kj1352 5 年前
父节点
当前提交
d882bc8ecf
共有 6 个文件被更改,包括 505 次插入7 次删除
  1. +77
    -1
      src/app/calendar/calendar.component.html
  2. +278
    -0
      src/app/calendar/calendar.component.scss
  3. +106
    -6
      src/app/calendar/calendar.component.ts
  4. +1
    -0
      src/app/tabs/home/home.component.scss
  5. +1
    -0
      src/app/welcome/welcome.component.scss
  6. +42
    -0
      src/assets/custom-icons/plus.svg

+ 77
- 1
src/app/calendar/calendar.component.html 查看文件

@@ -1 +1,77 @@
<p>calendar works!</p>
<div class="page">
<header class="nav-header">
<button class="close-button" (click)="back()">
<svg-icon [applyClass]="true" class="icon" src="assets/custom-icons/close.svg"></svg-icon>
</button>

<button class="profile-button" [routerLink]="['/profile']">
<img src="https://pbs.twimg.com/profile_images/3478244961/01ebfc40ecc194a2abc81e82ab877af4.jpeg">
</button>
</header>

<h2 class="calendar-header">
{{ selectedMonth }} {{ selectedYear }}
</h2>

<section class="mini-calendar">
<div class="days">
<span> S </span><span> M </span><span> T </span><span> W </span>
<span> T </span><span> F </span><span> S </span>
</div>
<div class="dates">
<span class="non-current-date" *ngFor="let preceedingDay of preceedingDays"> {{ preceedingDay }} </span>
<span [ngClass]="{'current-date': currentDate === selectedMonthDay && currentMonth === selectedMonth && currentYear === selectedYear,
'active': selectedDate === selectedMonthDay }"
*ngFor="let selectedMonthDay of selectedMonthDays"
(click)="selectedDate = selectedMonthDay">
{{ selectedMonthDay }}
</span>
<span class="non-current-date" *ngFor="let succeedingDay of succeedingDays">
{{ succeedingDay }}
</span>
</div>
</section>

<section class="schedule-details">
<header> {{ selectedDate }}, {{ selectedMonth }} {{ selectedYear }} </header>
<ul>
<li class="attended">
<svg-icon [applyClass]="true" class="icon checkmark" src="assets/custom-icons/checkmark.svg"></svg-icon>
<div class="content">
<label> Mathematics class </label>
<p> 8:00 AM to 10:00 AM </p>
</div>
<button> Attended </button>
</li>

<li class="absent">
<svg-icon [applyClass]="true" class="icon checkmark" src="assets/custom-icons/checkmark.svg"></svg-icon>
<div class="content">
<label> Physics class </label>
<p> 11:00 AM to 1:00 PM </p>
</div>
<button> Absent </button>
</li>

<li class="late">
<svg-icon [applyClass]="true" class="icon checkmark" src="assets/custom-icons/checkmark.svg"></svg-icon>
<div class="content">
<label> Chemistry class </label>
<p> 2:00 PM to 3:00 PM </p>
</div>
<button> Late </button>
</li>

<li class="progress">
<svg-icon [applyClass]="true" class="icon checkmark" src="assets/custom-icons/checkmark.svg"></svg-icon>
<div class="content">
<label> Social Science class </label>
<p> 4:00 AM to 5:00 PM </p>
</div>
<button> In Progress </button>
</li>
</ul>
</section>

<button class="add-button"> <svg-icon [applyClass]="true" class="icon" src="assets/custom-icons/plus.svg"></svg-icon> </button>
</div>

+ 278
- 0
src/app/calendar/calendar.component.scss 查看文件

@@ -0,0 +1,278 @@
.page {
height: 100vh;
overflow: auto;
background-color: var(--ash-black);
}


.nav-header {
background-color: var(--ash-black);
display: flex;
align-items: center;
padding: 0 5%;
height: 60px;
position: sticky;
position: -webkit-sticky;
top: 0;
z-index: 1;

.close-button {
border: 0px;
background-color: transparent;
.icon {
width: 16px;
height: 16px;
fill: var(--light-grey);
}
}

.profile-button {
background-color: transparent;
margin-left: auto;
border: 0px;
margin-top: 5px;
}

img {
width: 35px;
height: 35px;
border-radius: 50%;
overflow: hidden;
}
}

.calendar-header {
color: white;
font-size: 18px;
font-weight: 500;
padding: 0 5%;
}


.mini-calendar {
width: 100%;
margin: 10px auto;

.days {
display: flex;
width: 100vw;
margin: 0 auto 10px;
padding: 10px 0;
position: relative;

&::before {
content: '';
position: absolute;
bottom: 0;
left: 5%;
width: 90%;
height: 1px;
background-color: rgba(white, 0.1);
}

span {
width: calc(100vw / 7);
text-align: center;
font-size: 12px;
color: var(--light-grey);
}
}

.dates {
display: flex;
width: 100vw;
margin: 0 auto;
flex-wrap: wrap;

span {
display: block;
font-size: 13px;
width: calc(100vw / 7);
color: var(--light-grey);
font-weight: 500;
position: relative;
text-align: center;
transition: background-color 0.3s, color 0.3s;
height: calc(100vw / 7);
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;

&.current-date {
color: white;
font-weight: 600;
}

&.active {
background-color: var(--black);
color: white;
}

&.non-current-date {
color: var(--dark-grey);
}
}
}
}

.schedule-details {
max-height: calc(100vh - 60px);
background-color: white;
padding: 20px 5% 100px;
overflow: auto;
border-top-left-radius: 30px;
border-top-right-radius: 30px;

header {
color: var(--dark-grey);
font-size: 16px;
font-weight: 700;
}

ul {
list-style: none;
}

li {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
margin: 0px auto;
padding-top: 20px;
position: relative;

&.attended {
button {
background-color: var(--green);
}

&::before {
border-color: var(--green);
}

.checkmark {
fill: var(--green);
}
}

&.absent {
button {
background-color: rgba(red, 0.5);
}

&::before {
border-color: rgba(red, 0.5);
}

.checkmark {
fill: rgba(red, 0.5);
}
}

&.late {
button {
background-color: rgba(orange, 0.5);
}

&::before {
border-color: rgba(orange, 0.5);
}

.checkmark {
fill: rgba(orange, 0.5);
}
}

&.progress {
button {
background-color: var(--teal);
}

&::before {
border-color: var(--teal);
}

.checkmark {
fill: var(--teal);
}
}

&:last-child::before {
display: none;
}

&::before {
content: '';
position: absolute;
left: 8px;
top: 50%;
height: 100%;
width: 1px;
border-right: 1px dashed var(--light-grey);
}

.icon {
background-color: white;
z-index: 1;
position: relative;
width: 20px;
height: 20px;
fill: var(--light-grey);
}

button {
border-radius: 20px;
width: 90px;
height: 25px;
font-size: 12px;
border: 0px;
color: white;
background-color: var(--light-grey);
}

.content {
width: calc(100% - 40px - 120px);
}

label {
display: block;
font-size: 14px;
color: var(--dark-grey);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

p {
font-size: 12px;
color: var(--light-grey);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}

.add-button {
position: fixed;
right: 5%;
bottom: 20px;
z-index: 1;
width: 50px;
height: 50px;
border-radius: 50%;
border: 0px;
background-color: var(--teal-green);
box-shadow: 0px 0px 5px var(--teal-green);
display: flex;
align-items: center;
justify-content: center;

.icon {
width: 20px;
height: 20px;
fill: white;
}
}

+ 106
- 6
src/app/calendar/calendar.component.ts 查看文件

@@ -1,15 +1,115 @@
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';

@Component({
selector: 'app-calendar',
templateUrl: './calendar.component.html',
styleUrls: ['./calendar.component.scss']
selector: 'app-calendar',
templateUrl: './calendar.component.html',
styleUrls: ['./calendar.component.scss']
})
export class CalendarComponent implements OnInit {
currentDate: number;
currentMonth: string;
currentYear: number;
selectedDate: number;
selectedMonth: string;
selectedYear: number;
monthMap: Array<string> = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
preceedingDays: Array<number> = [];
succeedingDays: Array<number> = [];
selectedMonthDays: Array<number> = [];

constructor() { }
constructor(
private location: Location
) { }

ngOnInit(): void {
}
ngOnInit(): void {
this.selectToday();
}

back() {
this.location.back();
}

selectToday() {
this.selectedMonth = this.monthMap[(new Date()).getMonth()];
this.selectedYear = (new Date()).getFullYear();
this.selectedDate = new Date().getDate();

this.currentYear = (new Date()).getFullYear();
this.currentDate = new Date().getDate();
this.currentMonth = this.monthMap[(new Date()).getMonth()];

this.renderCalendar();
}

getMonthNumberFromMap(month: string) {
let index = this.monthMap.findIndex((mapmonth => mapmonth === month));
return (index + 1).toString().padStart(2, '0');
}

renderCalendar() {
// Generate dates for the calendar
let i = 1,
no_of_preceeding_days,
no_of_days_in_selected_month,
no_of_succeeding_days,
last_date_of_previous_month,
first_date_of_selected_month,
last_date_of_selected_month;

first_date_of_selected_month = new Date(this.selectedYear, this.monthMap.indexOf(this.selectedMonth), 1);

// Add one month, and subtract one day to the selected month and year
last_date_of_selected_month = new Date(this.selectedYear, this.monthMap.indexOf(this.selectedMonth) + 1, 0);
last_date_of_previous_month = new Date(this.selectedYear, this.monthMap.indexOf(this.selectedMonth), 0);

no_of_preceeding_days = first_date_of_selected_month.getDay();
no_of_days_in_selected_month = last_date_of_selected_month.getDate();
no_of_succeeding_days = 6 - last_date_of_selected_month.getDay();

this.preceedingDays = [];
this.selectedMonthDays = [];
this.succeedingDays = [];

for (i = no_of_preceeding_days - 1; i >= 0; i -= 1) {
this.preceedingDays.push(last_date_of_previous_month.getDate() - i);
}

for (i = 1; i <= no_of_days_in_selected_month; i += 1) {
this.selectedMonthDays.push(i);
}

for (i = 1; i <= no_of_succeeding_days; i += 1) {
this.succeedingDays.push(i);
}
}

selectNextMonth() {
let next_month_index = (this.monthMap.indexOf(this.selectedMonth) + 1) % this.monthMap.length;
this.selectedMonth = this.monthMap[next_month_index];
if (next_month_index == 0) {
this.selectedYear += 1;
}

this.renderCalendar();
}

selectPreviousMonth() {
let previous_month_index = (this.monthMap.indexOf(this.selectedMonth) + (this.monthMap.length - 1)) % this.monthMap.length;
this.selectedMonth = this.monthMap[previous_month_index];
if (previous_month_index == (this.monthMap.length - 1)) {
this.selectedYear -= 1;
}

this.renderCalendar();
}

selectPreviousYear() {
this.selectedYear -=1;
}

selectNextYear() {
this.selectedYear +=1;
}

}

+ 1
- 0
src/app/tabs/home/home.component.scss 查看文件

@@ -149,6 +149,7 @@
width: calc(100% - 180px);
border-left: 1px solid #cecece;
padding-left: 15px;
overflow: hidden;

p {
margin-top: 10px;


+ 1
- 0
src/app/welcome/welcome.component.scss 查看文件

@@ -87,6 +87,7 @@
width: calc(100% - 100px);
border-left: 1px solid #cecece;
padding-left: 15px;
overflow: hidden;

p {
margin-top: 10px;


+ 42
- 0
src/assets/custom-icons/plus.svg 查看文件

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 409.6 409.6" style="enable-background:new 0 0 409.6 409.6;" xml:space="preserve">
<g>
<g>
<path d="M392.533,187.733H221.867V17.067C221.867,7.641,214.226,0,204.8,0s-17.067,7.641-17.067,17.067v170.667H17.067
C7.641,187.733,0,195.374,0,204.8s7.641,17.067,17.067,17.067h170.667v170.667c0,9.426,7.641,17.067,17.067,17.067
s17.067-7.641,17.067-17.067V221.867h170.667c9.426,0,17.067-7.641,17.067-17.067S401.959,187.733,392.533,187.733z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>