Commit 7ecadc6b authored by 伊藤雄大's avatar 伊藤雄大

Merge branch 'itou' into 'develop'

デザインに合わせたプロトタイプ作成 See merge request !3
parents 57b2a597 3a4b2113
......@@ -29,6 +29,11 @@
"glob": "**/*.svg",
"input": "node_modules/ionicons/dist/ionicons/svg",
"output": "./svg"
},
{
"glob": "**/*.json",
"input": "src/data",
"output": "data"
}
],
"styles": [
......@@ -116,6 +121,11 @@
"glob": "**/*.svg",
"input": "node_modules/ionicons/dist/ionicons/svg",
"output": "./svg"
},
{
"glob": "**/*.json",
"input": "src/data",
"output": "data"
}
],
"styles": [
......@@ -150,7 +160,8 @@
"cli": {
"schematicCollections": [
"@ionic/angular-toolkit"
]
],
"analytics": false
},
"schematics": {
"@ionic/angular-toolkit:component": {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -13,56 +13,56 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^18.0.0",
"@angular/common": "^18.0.0",
"@angular/compiler": "^18.0.0",
"@angular/core": "^18.1.1",
"@angular/forms": "^18.0.0",
"@angular/platform-browser": "^18.0.0",
"@angular/platform-browser-dynamic": "^18.0.0",
"@angular/router": "^18.0.0",
"@aws-amplify/ui-angular": "^5.0.16",
"@capacitor/app": "6.0.0",
"@capacitor/core": "6.1.0",
"@capacitor/haptics": "6.0.0",
"@capacitor/keyboard": "6.0.1",
"@capacitor/status-bar": "6.0.0",
"@ionic/angular": "^8.0.0",
"aws-amplify": "^6.4.0",
"@angular/animations": "^18.2.8",
"@angular/common": "^18.2.8",
"@angular/compiler": "^18.2.8",
"@angular/core": "^18.2.8",
"@angular/forms": "^18.2.8",
"@angular/platform-browser": "^18.2.8",
"@angular/platform-browser-dynamic": "^18.2.8",
"@angular/router": "^18.2.8",
"@aws-amplify/ui-angular": "^5.0.29",
"@capacitor/app": "6.0.1",
"@capacitor/core": "6.1.2",
"@capacitor/haptics": "6.0.1",
"@capacitor/keyboard": "6.0.2",
"@capacitor/status-bar": "6.0.1",
"@ionic/angular": "^8.3.3",
"aws-amplify": "^6.6.6",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"ionicons": "^7.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
"ionicons": "^7.4.0",
"rxjs": "~7.8.1",
"tslib": "^2.8.0",
"zone.js": "~0.14.10"
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.0.0",
"@angular-eslint/builder": "^18.0.0",
"@angular-eslint/eslint-plugin": "^18.0.0",
"@angular-eslint/eslint-plugin-template": "^18.0.0",
"@angular-eslint/schematics": "^18.0.0",
"@angular-eslint/template-parser": "^18.0.0",
"@angular/cli": "^18.1.1",
"@angular/compiler-cli": "^18.0.0",
"@angular/language-service": "^18.0.0",
"@capacitor/cli": "6.1.0",
"@ionic/angular-toolkit": "^11.0.1",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^48.2.1",
"eslint-plugin-prefer-arrow": "1.2.2",
"jasmine-core": "~5.1.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.4.0",
"@angular-devkit/build-angular": "^18.2.9",
"@angular-eslint/builder": "^18.4.0",
"@angular-eslint/eslint-plugin": "^18.4.0",
"@angular-eslint/eslint-plugin-template": "^18.4.0",
"@angular-eslint/schematics": "^18.4.0",
"@angular-eslint/template-parser": "^18.4.0",
"@angular/cli": "^18.2.9",
"@angular/compiler-cli": "^18.2.8",
"@angular/language-service": "^18.2.8",
"@capacitor/cli": "6.1.2",
"@ionic/angular-toolkit": "^12.1.1",
"@types/jasmine": "~5.1.4",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"eslint": "^9.13.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.4.3",
"eslint-plugin-prefer-arrow": "1.2.3",
"jasmine-core": "~5.4.0",
"jasmine-spec-reporter": "~7.0.0",
"karma": "~6.4.4",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-coverage": "~2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.4.0"
"typescript": "^5.5.4"
},
"description": "An Ionic project"
}
}
\ No newline at end of file
......@@ -4,60 +4,32 @@ import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
loadChildren: () => import('./home/home.module').then(m => m.HomePageModule)
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
{
path: 'user-regist',
loadChildren: () => import('./user-regist/user-regist.module').then( m => m.UserRegistPageModule)
},
{
path: 'password-update',
loadChildren: () => import('./password-update/password-update.module').then( m => m.PasswordUpdatePageModule)
},
{
path: 'menu',
loadChildren: () => import('./menu/menu.module').then( m => m.MenuPageModule)
},
{
path: 'card-select',
loadChildren: () => import('./card-select/card-select.module').then( m => m.CardSelectPageModule)
loadChildren: () => import('./card-select/card-select.module').then(m => m.CardSelectPageModule)
},
{
path: 'card-regist',
loadChildren: () => import('./card-regist/card-regist.module').then( m => m.CardRegistPageModule)
loadChildren: () => import('./card-regist/card-regist.module').then(m => m.CardRegistPageModule)
},
{
path: 'pass-select',
loadChildren: () => import('./pass-select/pass-select.module').then( m => m.PassSelectPageModule)
loadChildren: () => import('./pass-select/pass-select.module').then(m => m.PassSelectPageModule)
},
{
path: 'pass-regist',
loadChildren: () => import('./pass-regist/pass-regist.module').then( m => m.PassRegistPageModule)
},
{
path: 'pass-change',
loadChildren: () => import('./pass-change/pass-change.module').then( m => m.PassChangePageModule)
},
{
path: 'pass-continue',
loadChildren: () => import('./pass-continue/pass-continue.module').then( m => m.PassContinuePageModule)
},
{
path: 'pass-refund',
loadChildren: () => import('./pass-refund/pass-refund.module').then( m => m.PassRefundPageModule)
},
{
path: 'history',
loadChildren: () => import('./history/history.module').then( m => m.HistoryPageModule)
loadChildren: () => import('./pass-regist/pass-regist.module').then(m => m.PassRegistPageModule)
},
{
path: 'deny-list',
loadChildren: () => import('./deny-list/deny-list.module').then( m => m.DenyListPageModule)
path: 'claim-list',
loadChildren: () => import('./claim-list/claim-list.module').then(m => m.ClaimListPageModule)
},
];
......
......@@ -7,6 +7,8 @@ import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
@NgModule({
declarations: [AppComponent],
imports: [
......@@ -14,7 +16,7 @@ import { AppRoutingModule } from './app-routing.module';
IonicModule.forRoot(),
AppRoutingModule
],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, provideHttpClient(withInterceptorsFromDi())],
bootstrap: [AppComponent]
})
export class AppModule { }
<ion-header [translucent]="true">
<ion-header>
<app-header [mode]="1" (clickClose)="onClickClose()"></app-header>
</ion-header>
......@@ -30,7 +30,7 @@
<ion-row>
<ion-col>
<ion-item>
<ion-input label="CVC" [value]="cvc"></ion-input>
<ion-input label="CVV" [value]="cvc"></ion-input>
</ion-item>
</ion-col>
</ion-row>
......
......@@ -5,13 +5,46 @@
<ion-grid class="ion-no-padding">
<ion-row>
<ion-col style="width:75%;padding-top:8px;padding-left:10px;">
<ion-label>クレジットカード</ion-label>
@switch (creditCardModel?.cardKind) {
@case (0) {
<ion-label>JCB</ion-label>
}
@case (1) {
<ion-label>Visa</ion-label>
}
@case (2) {
<ion-label>MasterCard</ion-label>
}
@case (3) {
<ion-label>AmericanExpress</ion-label>
}
@case (4) {
<ion-label>Diners</ion-label>
}
}
</ion-col>
<ion-col size="auto" style="padding-top:8px;">
<div class="common-link" (click)="onClickPass()">定期券</div>
<ion-col style="padding-top:8px;padding-right:10px;">
@if (creditCardModel?.denyStatus == 1 && creditCardModel?.deleteDeny == 0) {
<div [id]="denyStatusId" role="button" class="text-decoration-underline label-orange"
style="text-align:right;">
拒否リスト削除</div>
<ion-alert [trigger]="denyStatusId" header="拒否リスト削除しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickDenyStatus($event)"></ion-alert>
} @else if (creditCardModel?.denyStatus == 1 && creditCardModel?.deleteDeny == 1) {
<div [id]="deleteDenyId" role="button" class="text-decoration-underline label-orange"
style="text-align:right;">
依賴取消</div>
<div class="label-gray" style="font-size:12px;text-align:right;">
拒否リスト削除依賴済
</div>
<ion-alert [trigger]="deleteDenyId" header="拒否リスト削除依頼を取消しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickDenyStatus($event)"></ion-alert>
}
</ion-col>
<ion-col size="auto" align="right" style="padding-top:10px;padding-right:10px;">
<ion-icon name="trash-outline"></ion-icon>
<input type="button" [id]="deleteCardId" class="btn btn-outline-dark" value="削除">
<ion-alert [trigger]="deleteCardId" header="クレジットカードを削除しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickTrash($event)"></ion-alert>
</ion-col>
</ion-row>
</ion-grid>
......@@ -19,7 +52,7 @@
</ion-row>
<ion-row>
<ion-col style="padding-left:10px;padding-top:10px;" size="auto">
<div style="width:120px;">カード番号</div>
<div class="label-blue" style="width:120px;">カード番号</div>
</ion-col>
<ion-col style="padding-top:10px;">
<ion-grid class="ion-no-padding">
......@@ -50,20 +83,12 @@
</ion-grid>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="padding-left:10px;padding-top:10px;" size="auto">
<div style="width:120px;">カード名義人</div>
</ion-col>
<ion-col style="padding-top:10px;">
<ion-label>{{creditCardModel?.cardOwner}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="padding-left:10px;padding-top:10px;padding-bottom:10px;" size="auto">
<div style="width:120px;">有効期限</div>
<div class="label-blue" style="width:120px;">カード名義人</div>
</ion-col>
<ion-col style="padding-top:10px;padding-bottom:10px;">
<ion-label>{{creditCardModel?.cardYear}}年{{creditCardModel?.cardMonth}}月</ion-label>
<ion-label>{{creditCardModel?.cardOwner}}</ion-label>
</ion-col>
</ion-row>
</ion-grid>
......
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { CreditCardModel } from 'src/app/model/credit-card.model';
......@@ -14,28 +14,51 @@ import { CreditCardModel } from 'src/app/model/credit-card.model';
IonicModule
]
})
export class CardInfoComponent {
export class CardInfoComponent implements OnInit {
//クレジットカード情報
@Input() creditCardModel?: CreditCardModel;
@Output() clickPass: EventEmitter<void> = new EventEmitter();
@Output() clickDenyStatus: EventEmitter<void> = new EventEmitter();
@Output() clickTrash: EventEmitter<void> = new EventEmitter();
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
denyStatusId?: string;
deleteDenyId?: string;
deleteCardId?: string;
/**
* コンストラクタ
*/
constructor() { }
ngOnInit(): void {
this.denyStatusId = "denuStatus" + this.creditCardModel?.cardNumber;
this.deleteDenyId = "deleteDeny" + this.creditCardModel?.cardNumber;
this.deleteCardId = "deleteCard" + this.creditCardModel?.cardNumber;
}
/**
* 定期券
* 拒否リスト状態
*/
onClickPass(): void {
this.clickPass.emit();
onClickDenyStatus(event: any): void {
if (event.detail.role === 'confirm') {
this.clickDenyStatus.emit();
}
}
/**
* 削除
*/
onClickTrash(): void {
onClickTrash(event: any): void {
this.clickTrash.emit();
}
}
<ion-header [translucent]="true">
<ion-header>
<app-header [mode]="2" (clickBack)="onClickBack()"></app-header>
</ion-header>
......@@ -6,12 +6,12 @@
<div style="margin-top:10px;margin-left:10px;margin-right:10px;">
@for (model of cardList;track model.cardNumber) {
<div style="margin-top:10px;">
<app-card-info [creditCardModel]="model" (clickPass)="onClickPass(model)"
<app-card-info [creditCardModel]="model" (clickDenyStatus)="onClickDenyStatus(model)"
(clickTrash)="onClickTrash(model)"></app-card-info>
</div>
}
</div>
<div role="button" style="margin-top:10px;text-align:center;" class="add-link" (click)="onClickAddCard()">
<span>+&nbsp;クレジットカードを追加する</span>
<div role="button" style="margin-top:20px;text-align:center;" class="label-orange" (click)="onClickAddCard()">
<span>クレジットカードを追加する<ion-icon name="add-circle-outline"></ion-icon></span>
</div>
</ion-content>
\ No newline at end of file
......@@ -25,16 +25,17 @@ export class CardSelectPage implements OnInit {
* 初期化
*/
ngOnInit(): void {
this.cardList = this.cardService.getList(this.routeService.customerId);
//this.cardList = this.cardService.getList(this.routeService.customerId);
this.cardService.getList(this.routeService.customerId).subscribe((ret: CreditCardModel[]) => {
this.cardList = ret;
});
}
/**
* 戻る
*/
onClickBack(): void {
if (this.routeService.customerId) {
this.routeService.navigateMenu(this.routeService.customerId);
}
this.routeService.navigateHome();
}
/**
......@@ -45,11 +46,17 @@ export class CardSelectPage implements OnInit {
}
/**
* 定期券
* 拒否リスト状態
* @param model クレジットカード情報
*/
onClickPass(model: CreditCardModel): void {
this.routeService.navigatePassSelect(model.tokenId, model.cardNumber);
onClickDenyStatus(model: CreditCardModel): void {
if (this.cardList) {
for (let i = 0; i < this.cardList?.length; i++) {
if (this.cardList[i].tokenId === model.tokenId && this.cardList[i].denyStatus == 1) {
this.cardList[i].deleteDeny = this.cardList[i].deleteDeny == 0 ? 1 : 0;
}
}
}
}
/**
......
<ion-card>
<ion-grid>
<ion-row>
<ion-col>
<ion-label style="font-size:16px;">{{model.agencyName}}</ion-label>
</ion-col>
<ion-col style="text-align:right;">
@if (model.cancelRequest == 0) {
<div role="button" id="cancelReq" class="text-decoration-underline label-orange"
(click)="onClickBefCancelReq()">取消依頼
</div>
<ion-alert [isOpen]="isCancelOpen" header="取消依頼しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickCancelReq($event)"></ion-alert>
} @else {
<div role="button" id="cancelReqDone" class="text-decoration-underline label-orange"
(click)="onClickBefCancelReq()">
取消依頼済</div>
<ion-alert [isOpen]="isCancelOpen" header="取消依頼を解除しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickCancelReq($event)"></ion-alert>
}
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<table width="100%">
<tr>
<td>
<ion-label class="label-blue">請求結果</ion-label>
</td>
<td>
<ion-label>{{model.result}}</ion-label>
</td>
<td style="width:120px;"></td>
</tr>
<tr>
<td>
<ion-label class="label-blue">購入日</ion-label>
</td>
<td>
<ion-label>{{model.earningDate | customDate}}</ion-label>
</td>
<td style="width:120px;"></td>
</tr>
<tr>
@if (model.ngFlag == 1) {
<td>
<ion-label class="label-red">カードご利用額</ion-label>
</td>
<td>
<ion-label class="label-red">{{model.amount | number}}円</ion-label>
</td>
<td style="width:120px;">
@if (model.payRequest == 0) {
<input type="button" id="payReq" class="btn pay-button" (click)="onClickBefPayReq()" value="支払要求">
<ion-alert [isOpen]="isPayOpen" header="支払要求しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickPayReq($event)"></ion-alert>
} @else {
<input type="button" id="payReqDone" class="btn pay-button" (click)="onClickBefPayReq()" value="支払要求取消">
<div class="label-gray" style="font-size:12px;text-align:right;">
支払要求済
</div>
<ion-alert [isOpen]="isPayOpen" header="支払要求を解除しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickPayReq($event)"></ion-alert>
}
</td>
} @else {
<td>
<ion-label class="label-blue">カードご利用額</ion-label>
</td>
<td>
<ion-label>{{model.amount | number}}円</ion-label>
</td>
<td style="width:120px;"></td>
}
</tr>
</table>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-accordion-group>
<ion-accordion value="detail">
<ion-item slot="header" style="text-align:center;">
<ion-label>内訳</ion-label>
</ion-item>
<div class="ion-padding" slot="content">
@for (detail of model.detailList;track detail.getonDt) {
<ion-card>
<table width="100%" style="margin:20px;">
<tr>
<td>
<ion-label>{{detail.routeName}}</ion-label>
</td>
<td>
<ion-label>{{detail.getonStopName}}~{{detail.getoffStopName}}</ion-label>
</td>
</tr>
<tr>
<td>
<ion-label>乗車日時:</ion-label>
</td>
<td>
<ion-label>{{detail.getonDt | customDatetime}}</ion-label>
</td>
</tr>
<tr>
<td>
<ion-label>降車日時:</ion-label>
</td>
<td>
<ion-label>{{detail.getoffDt | customDatetime}}</ion-label>
</td>
</tr>
<tr>
<td>
<ion-label>料  金:</ion-label>
</td>
<td>
<ion-label>{{detail.price|number}}円</ion-label>
</td>
</tr>
</table>
</ion-card>
}
</div>
</ion-accordion>
</ion-accordion-group>
</ion-col>
</ion-row>
</ion-grid>
</ion-card>
\ No newline at end of file
.pay-button {
color: #f5404b;
background-color: #fef5f6;
}
.label-red {
color: #f5404b;
}
\ No newline at end of file
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { DenyInfoComponent } from './deny-info.component';
import { ClaimInfoComponent } from './claim-info.component';
describe('DenyInfoComponent', () => {
let component: DenyInfoComponent;
let fixture: ComponentFixture<DenyInfoComponent>;
describe('ClaimInfoComponent', () => {
let component: ClaimInfoComponent;
let fixture: ComponentFixture<ClaimInfoComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ DenyInfoComponent ],
declarations: [ ClaimInfoComponent ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(DenyInfoComponent);
fixture = TestBed.createComponent(ClaimInfoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
......
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { ClaimListModel } from 'src/app/model/claim-list.model';
import { CustomDatePipe } from 'src/app/pipe/custom-date.pipe';
import { CustomDatetimePipe } from 'src/app/pipe/custom-datetime.pipe';
import { DecimalPipe } from '@angular/common';
/**
* 請求一覧情報
*/
@Component({
standalone: true,
selector: 'app-claim-info',
templateUrl: './claim-info.component.html',
styleUrls: ['./claim-info.component.scss'],
imports: [
IonicModule,
CustomDatePipe,
CustomDatetimePipe,
DecimalPipe
]
})
export class ClaimInfoComponent implements OnInit {
@Input() model: ClaimListModel = new ClaimListModel();
@Output() clickPayReq: EventEmitter<ClaimListModel> = new EventEmitter<ClaimListModel>();
@Output() clickCancelReq: EventEmitter<ClaimListModel> = new EventEmitter<ClaimListModel>();
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//取消依頼メッセージダイアログ表示有無
isCancelOpen: boolean = false;
//支払要求メッセージダイアログ表示有無
isPayOpen: boolean = false;
/**
* コンストラクタ
*/
constructor() { }
/**
* 初期化
*/
ngOnInit(): void {
}
/**
* 拒否リスト情報取得
* @returns 拒否リスト情報
*/
getModel(): ClaimListModel {
return this.model;
}
/**
* 取消依頼ダイアログを表示する前の処理
*/
onClickBefCancelReq(): void {
if (this.model.payRequest === 1) {
//既に支払要求済の場合は取消させない
alert("既に支払要求済となっています。")
return;
}
this.isCancelOpen = true;
}
/**
* 取消依頼ダイアログ
* @param event
*/
onClickCancelReq(event: any): void {
if (event.detail.role === 'confirm') {
this.clickCancelReq.emit(this.model);
}
this.isCancelOpen = false;
}
/**
* 支払要求ダイアログを表示する前の処理
*/
onClickBefPayReq(): void {
if (this.model.cancelRequest === 1) {
//既に取消依頼済の場合は支払要求させない
alert("既に取消依頼済となっています。");
return;
}
this.isPayOpen = true;
}
/**
* 支払要求ダイアログ
* @param event
*/
onClickPayReq(event: any): void {
if (event.detail.role === 'confirm') {
this.clickPayReq.emit(this.model);
}
this.isPayOpen = false;
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DenyListPage } from './deny-list.page';
import { ClaimListPage } from './claim-list.page';
const routes: Routes = [
{
path: '',
component: DenyListPage
component: ClaimListPage
}
];
......@@ -14,4 +14,4 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class DenyListPageRoutingModule {}
export class ClaimListPageRoutingModule {}
......@@ -4,20 +4,22 @@ import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { MenuPageRoutingModule } from './menu-routing.module';
import { ClaimListPageRoutingModule } from './claim-list-routing.module';
import { MenuPage } from './menu.page';
import { ClaimListPage } from './claim-list.page';
import { HeaderComponent } from '../common/header/header.component';
import { ClaimInfoComponent } from './claim-info/claim-info.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
MenuPageRoutingModule,
ClaimListPageRoutingModule,
ClaimInfoComponent,
HeaderComponent
],
declarations: [MenuPage]
declarations: [ClaimListPage]
})
export class MenuPageModule { }
export class ClaimListPageModule { }
<ion-header>
<app-header [mode]="2" (clickBack)="onClickBack()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid>
<ion-row>
<ion-col style="text-align:center;">
<div (click)="onClickPrev()">
<ion-icon name="chevron-back-outline" size="large" class="label-blue"></ion-icon>
</div>
</ion-col>
<ion-col size="auto">
<ion-datetime-button datetime="datetime"></ion-datetime-button>
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime" presentation="date"></ion-datetime>
</ng-template>
</ion-modal>
</ion-col>
<ion-col style="text-align:center;">
<div (click)="onClickNext()">
<ion-icon name="chevron-forward-outline" size="large" class="label-blue"></ion-icon>
</div>
</ion-col>
</ion-row>
</ion-grid>
@for(model of claimList;track model.tokenId) {
<div style="margin-top:10px;margin-left:10px;margin-right:10px;">
<app-claim-info [model]="model" (clickPayReq)="onClickPayReq($event)"
(clickCancelReq)="onClickCancelReq($event)"></app-claim-info>
</div>
}
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HistoryPage } from './history.page';
import { ClaimListPage } from './claim-list.page';
describe('HistoryPage', () => {
let component: HistoryPage;
let fixture: ComponentFixture<HistoryPage>;
describe('ClaimListPage', () => {
let component: ClaimListPage;
let fixture: ComponentFixture<ClaimListPage>;
beforeEach(() => {
fixture = TestBed.createComponent(HistoryPage);
fixture = TestBed.createComponent(ClaimListPage);
component = fixture.componentInstance;
fixture.detectChanges();
});
......
import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { ClaimListModel } from '../model/claim-list.model';
import { RouteService } from '../services/route.service';
import { ClaimInfoComponent } from './claim-info/claim-info.component';
import { ClaimlistService } from '../services/claimlist.service';
/**
* 拒否リスト
*/
@Component({
selector: 'app-claim-list',
templateUrl: './claim-list.page.html',
styleUrls: ['./claim-list.page.scss'],
})
export class ClaimListPage implements OnInit {
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//請求一覧
claimList?: ClaimListModel[];
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param claimListService 請求一覧サービス
*/
constructor(private routeService: RouteService, private claimListService: ClaimlistService) { }
/**
* 初期化
*/
ngOnInit() {
//this.claimList = this.claimListService.getList(this.routeService.customerId);
this.claimListService.getList("").subscribe((ret: ClaimListModel[]) => {
this.claimList = ret;
});
}
/**
* 戻る
*/
onClickBack(): void {
this.routeService.navigateHome();
}
/**
* 支払要求
* @param model 請求情報
*/
onClickPayReq(model: ClaimListModel): void {
if (this.claimList) {
for (let i = 0; i < this.claimList.length; i++) {
if (this.claimList[i].tokenId === model.tokenId && this.claimList[i].earningDate === model.earningDate) {
this.claimList[i].payRequest = this.claimList[i].payRequest === 0 ? 1 : 0;
break;
}
}
}
}
/**
* 取消依頼
* @param model 請求情報
*/
onClickCancelReq(model: ClaimListModel): void {
if (this.claimList) {
for (let i = 0; i < this.claimList.length; i++) {
if (this.claimList[i].tokenId === model.tokenId && this.claimList[i].earningDate === model.earningDate) {
this.claimList[i].cancelRequest = this.claimList[i].cancelRequest === 0 ? 1 : 0;
break;
}
}
}
}
onClickPrev(): void {
}
onClickNext(): void {
}
}
<div class="title-label" [class.right-align]="mode === 1 || mode === 3">
@if (mode === 0) {
<div style="margin-left:10px;padding-top:5px;">タッチ決済サービス</div>
}
<div class="title-label" [class.right-align]="mode === 1">
@if (mode === 2) {
<div style="margin-left:5px;padding-top:5px;" (click)="onClickBack()">
<ion-icon name="chevron-back-outline" size="large"></ion-icon>
<div style="margin-left:5px;" (click)="onClickBack()">
<table>
<tr>
<td style="padding-top:5px;">
<ion-icon name="chevron-back-outline" size="large"></ion-icon>
</td>
<td>
<span style="font-size:20px;">Back</span>
</td>
</tr>
</table>
</div>
}
@if (mode === 1) {
......@@ -12,16 +18,4 @@
<ion-icon name="close-outline" size="large"></ion-icon>
</div>
}
@if (mode === 3) {
<ion-grid width="100%">
<ion-row>
<ion-col style="padding-top:3px;text-align:right;">
<div (click)="onClickLogout()">ログアウト</div>
</ion-col>
<ion-col style="padding-top:5px;padding-left:5px;padding-right:10px;" size="auto">
<ion-icon name="settings-outline"></ion-icon>
</ion-col>
</ion-row>
</ion-grid>
}
</div>
\ No newline at end of file
.title-label {
background-color: #0CACCD;
background-color: #0DACCD;
color: white;
height: 40px;
}
......
......@@ -46,12 +46,4 @@ export class HeaderComponent {
this.routeService.navigateHome();
}
/**
* 利用者情報更新
*/
onClickSetting(): void {
if (this.routeService.customerId) {
this.routeService.navigateUserRegist(1, this.routeService.customerId);
}
}
}
<div class="border rounded">
<ion-grid class="</ion-label>">
<ion-row>
<ion-col style="padding-left:10px;" size="auto">
<ion-checkbox class="form-check-input" style="margin-top:80px;"
(change)="onChangeSelect($event)"></ion-checkbox>
</ion-col>
<ion-col>
<ion-grid class="</ion-label>">
<ion-row>
<ion-col style="padding-top:10px;">
<ion-label>{{model.getonStopName}}→{{model.getoffStopName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="padding-top:10px;" size="auto">
<div style="width:80px;">乗車</div>
</ion-col>
<ion-col style="padding-top:10px;">
<ion-label>{{model.getonDt}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="padding-top:10px;" size="auto">
<div style="width:80px;">降車</div>
</ion-col>
<ion-col style="padding-top:10px;">
<ion-label>{{model.getoffDt}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="padding-top:10px;padding-bottom:10px;" size="auto">
<div style="width:80px;">請求金額</div>
</ion-col>
<ion-col style="padding-top:10px;padding-bottom:10px;">
<ion-label>{{amountStr}}円</ion-label>
</ion-col>
</ion-row>
</ion-grid>
</ion-col>
</ion-row>
</ion-grid>
</div>
\ No newline at end of file
import { Component, Input, OnInit } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { DenyListModel } from 'src/app/model/deny-list.model';
/**
* 拒否リスト情報
*/
@Component({
standalone: true,
selector: 'app-deny-info',
templateUrl: './deny-info.component.html',
styleUrls: ['./deny-info.component.scss'],
imports: [
IonicModule
]
})
export class DenyInfoComponent implements OnInit {
@Input() model: DenyListModel = new DenyListModel();
amountStr?: string;
/**
* コンストラクタ
*/
constructor() { }
/**
* 初期化
*/
ngOnInit(): void {
this.amountStr = this.model.amount.toLocaleString();
}
/**
* 選択イベント
* @param event イベント情報
*/
onChangeSelect(event: any) {
this.model.select = event.target.checked;
}
/**
* 拒否リスト情報取得
* @returns 拒否リスト情報
*/
getModel(): DenyListModel {
return this.model;
}
}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { DenyListPageRoutingModule } from './deny-list-routing.module';
import { DenyListPage } from './deny-list.page';
import { HeaderComponent } from '../common/header/header.component';
import { DenyInfoComponent } from './deny-info/deny-info.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
DenyListPageRoutingModule,
DenyInfoComponent,
HeaderComponent
],
declarations: [DenyListPage]
})
export class DenyListPageModule { }
<ion-header [translucent]="true">
<app-header [mode]="2" (clickBack)="onClickBack()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
@for(model of denyList;track model.getonStopId) {
<div style="margin-top:10px;margin-left:10px;margin-right:10px;">
<app-deny-info [model]="model"></app-deny-info>
</div>
}
<div style="margin-top:20px;text-align:center;">
<ion-button id="delreq" class="common-button rounded" style="margin-top:20px;">削除依頼</ion-button>
<ion-alert trigger="delreq" header="拒否リストからの削除を依頼しますか?" [buttons]="confirmButtons"
(didDismiss)="onClickDelreq($event)"></ion-alert>
</div>
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DenyListPage } from './deny-list.page';
describe('DenyListPage', () => {
let component: DenyListPage;
let fixture: ComponentFixture<DenyListPage>;
beforeEach(() => {
fixture = TestBed.createComponent(DenyListPage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { DenyListModel } from '../model/deny-list.model';
import { RouteService } from '../services/route.service';
import { DenyInfoComponent } from './deny-info/deny-info.component';
import { DenylistService } from '../services/denylist.service';
/**
* 拒否リスト
*/
@Component({
selector: 'app-deny-list',
templateUrl: './deny-list.page.html',
styleUrls: ['./deny-list.page.scss'],
})
export class DenyListPage implements OnInit {
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//拒否リスト
denyList?: DenyListModel[];
@ViewChildren(DenyInfoComponent) denyInfoList?: QueryList<DenyInfoComponent>;
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param denyListService 拒否リストサービス
*/
constructor(private routeService: RouteService, private denyListService: DenylistService) { }
/**
* 初期化
*/
ngOnInit() {
if (this.routeService.customerId) {
this.denyList = this.denyListService.getList(this.routeService.customerId);
}
}
/**
* 戻る
*/
onClickBack(): void {
if (this.routeService.customerId) {
this.routeService.navigateMenu(this.routeService.customerId);
}
}
/**
* 削除依頼
*/
onClickDelreq(event: any): void {
if (event.detail.role === 'confirm') {
let req: DenyListModel[] = [];
this.denyInfoList?.forEach(child => {
let model = child.getModel();
if (model.select) {
//拒否リスト削除依頼
req.push(model);
}
});
this.denyListService.reqDelete(req);
}
if (this.routeService.customerId) {
this.routeService.navigateMenu(this.routeService.customerId);
}
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HistoryPage } from './history.page';
const routes: Routes = [
{
path: '',
component: HistoryPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class HistoryPageRoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { HistoryPageRoutingModule } from './history-routing.module';
import { HistoryPage } from './history.page';
import { HeaderComponent } from '../common/header/header.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
HistoryPageRoutingModule,
HeaderComponent
],
declarations: [HistoryPage]
})
export class HistoryPageModule { }
<ion-header [translucent]="true">
<app-header [mode]="2" (clickBack)="onClickBack()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid style="margin-top:20px;">
<ion-row>
<ion-col class="ion-text-right" style="padding-top:8px;">
<ion-icon role="button" name="chevron-back-outline" size="large" (click)="onClickBefore()"></ion-icon>
</ion-col>
<ion-col>
<ion-datetime-button style="width:160px;" datetime="datetime"></ion-datetime-button>
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime" presentation="date" [(ngModel)]="searchDate" [showDefaultButtons]="true"
(ionChange)="onChangeDate($event)"></ion-datetime>
</ng-template>
</ion-modal>
</ion-col>
<ion-col style="padding-top:8px;">
<ion-icon role="button" name="chevron-forward-outline" size="large" (click)="onClickAfter()"></ion-icon>
</ion-col>
</ion-row>
@for (history of historyList;track history.getonoffDt) {
<ion-row>
<ion-col size="auto">
<ion-label>{{history.getonoffDt}}</ion-label>
</ion-col>
<ion-col size="auto">
@if (history.kind === "1") {
<ion-label>乗車</ion-label>
} @else {
<ion-label>降車</ion-label>
}
</ion-col>
<ion-col size="auto">
<ion-label>{{history.stopName}}</ion-label>
</ion-col>
<ion-col>
@if (history.kind === "1") {
@if (history.status === 0) {
<ion-label>乗車中</ion-label>
}
} @else {
<ion-label>{{history.fare|number}}円</ion-label>
}
</ion-col>
</ion-row>
}
</ion-grid>
</ion-content>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { RouteService } from '../services/route.service';
import { HistoryModel } from '../model/history.model';
import { HistoryService } from '../services/history.service';
/**
* 乗車履歴閲覧画面
*/
@Component({
selector: 'app-history',
templateUrl: './history.page.html',
styleUrls: ['./history.page.scss'],
})
export class HistoryPage implements OnInit {
searchDate?: string;
//乗車履歴
historyList?: HistoryModel[];
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param historyService 乗降履歴サービス
*/
constructor(private routeService: RouteService, private historyService: HistoryService) { }
/**
* 初期化
*/
ngOnInit() {
this.searchDate = (new Date()).toLocaleDateString("ja-JP", {
year: "numeric",
month: "2-digit",
day: "2-digit",
}).split("/").join("-");
if (this.routeService.customerId) {
this.historyList = this.historyService.getHistoryList(this.routeService.customerId, this.searchDate);
}
}
/**
* 戻る
*/
onClickBack(): void {
if (this.routeService.customerId) {
this.routeService.navigateMenu(this.routeService.customerId);
}
}
/**
* 前日へ
*/
onClickBefore() {
if (this.searchDate) {
let date = new Date(this.searchDate);
date.setDate(date.getDate() - 1);
this.searchDate = date.toLocaleDateString("ja-JP", {
year: "numeric",
month: "2-digit",
day: "2-digit",
}).split("/").join("-");
if (this.routeService.customerId) {
this.historyList = this.historyService.getHistoryList(this.routeService.customerId, this.searchDate);
}
}
}
/**
* 翌日へ
*/
onClickAfter() {
if (this.searchDate) {
let date = new Date(this.searchDate);
date.setDate(date.getDate() + 1);
this.searchDate = date.toLocaleDateString("ja-JP", {
year: "numeric",
month: "2-digit",
day: "2-digit",
}).split("/").join("-");
if (this.routeService.customerId) {
this.historyList = this.historyService.getHistoryList(this.routeService.customerId, this.searchDate);
}
}
}
/**
* 日付指定
* @param event イベント情報
*/
onChangeDate(event: any): void {
if (this.routeService.customerId) {
this.historyList = this.historyService.getHistoryList(this.routeService.customerId, event.target.value);
}
}
}
<ion-header [translucent]="true">
<app-header [mode]="0"></app-header>
<ion-header>
<app-header [mode]="3"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="email" label="メールアドレス" [(ngModel)]="email" [maxlength]="50"></ion-input>
</ion-item>
<ion-button class="rounded menu-button" style="margin-top:20px;"
(click)="onClickCardSelect()">クレジットカード一覧</ion-button>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="password" label="パスワード" [(ngModel)]="password" [maxlength]="20">
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
</ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<ion-button class="common-button rounded" style="margin-top:20px;" (click)="onClickLogin()">ログイン</ion-button>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<div role="button" class="common-link" style="font-size:12px;margin-top:20px;" (click)="onClickRegist()">
初めての方はこちら</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<div role="button" class="common-link" style="font-size:12px;" (click)="onClickPassword()">パスワードを忘れた方はこちら</div>
<ion-button class="rounded menu-button" style="margin-top:10px;" value=""
(click)="onClickClaimList()">請求一覧</ion-button>
</ion-col>
</ion-row>
</ion-grid>
......
#container {
text-align: center;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
#container strong {
font-size: 20px;
line-height: 26px;
}
#container p {
font-size: 16px;
line-height: 22px;
color: #8c8c8c;
margin: 0;
}
#container a {
text-decoration: none;
.menu-button {
width: 100%;
height: 60px;
--width: 100%;
--height: 60px;
--background: #f0f0f0;
--color: black;
}
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { RouteService } from '../services/route.service';
import { LoginService } from '../services/login.service';
/**
* ログイン画面
......@@ -10,58 +9,33 @@ import { LoginService } from '../services/login.service';
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
//メールアドレス
email?: string;
//パスワード
password?: string;
export class HomePage {
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param loginService ログイン処理サービス
* @param routeServive 画面遷移サービス
*/
constructor(private routeService: RouteService, private loginService: LoginService) { }
constructor(private routeServive: RouteService) { }
/**
* 初期化
*/
ngOnInit(): void {
this.email = "";
this.password = "";
}
/**
* ログイン
* ログアウト
*/
onClickLogin(): void {
if (!this.email) {
alert("メールアドレスが入力されていません")
return;
}
if (!this.password) {
alert("パスワードが入力されていません");
return;
}
if (this.loginService.login(this.email, this.password)) {
//TODO
this.routeService.navigateMenu("0000");
}
onClickLogout(): void {
this.routeServive.navigateHome();
}
/**
* 利用者登録
* クレジットカード選択
*/
onClickRegist(): void {
this.routeService.navigateUserRegist(0, "");
onClickCardSelect(): void {
this.routeServive.navigateCardSelect();
}
/**
* パスワード更新
* 請求一覧
*/
onClickPassword(): void {
this.routeService.navigatePasswordUpdate();
onClickClaimList(): void {
this.routeServive.navigateClaimList();
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MenuPage } from './menu.page';
const routes: Routes = [
{
path: '',
component: MenuPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class MenuPageRoutingModule {}
<ion-header [translucent]="true">
<app-header [mode]="3" (clickLogout)="onClickLogout()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid>
<ion-row>
<ion-col>
<ion-button class="rounded menu-button" style="margin-top:20px;"
(click)="onClickCardSelect()">クレジットカード一覧</ion-button>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-button class="rounded menu-button" style="margin-top:10px;" (click)="onClickHistory()">乗降履歴</ion-button>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-button class="rounded menu-button" style="margin-top:10px;" value=""
(click)="onClickDenyList()">拒否リスト</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
\ No newline at end of file
.menu-button {
width: 100%;
height: 60px;
--width: 100%;
--height: 60px;
--background: #f0f0f0;
--color: black;
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuPage } from './menu.page';
describe('MenuPage', () => {
let component: MenuPage;
let fixture: ComponentFixture<MenuPage>;
beforeEach(() => {
fixture = TestBed.createComponent(MenuPage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component } from '@angular/core';
import { RouteService } from '../services/route.service';
/**
* メニュー画面
*/
@Component({
selector: 'app-menu',
templateUrl: './menu.page.html',
styleUrls: ['./menu.page.scss'],
})
export class MenuPage {
/**
* コンストラクタ
* @param routeServive 画面遷移サービス
*/
constructor(private routeServive: RouteService) { }
/**
* ログアウト
*/
onClickLogout(): void {
this.routeServive.navigateHome();
}
/**
* クレジットカード選択
*/
onClickCardSelect(): void {
this.routeServive.navigateCardSelect();
}
/**
* 乗降履歴
*/
onClickHistory(): void {
this.routeServive.navigateHistory();
}
/**
* 拒否リスト
*/
onClickDenyList(): void {
this.routeServive.navigateDenyList();
}
}
/**
* 拒否リスト情報
* 請求情報
*/
export class DenyListModel {
//選択状態
select: boolean = false;
//乗車停留所ID
getonStopId?: string;
export class ClaimListModel {
//トークンID
tokenId?: string;
//事業者ID
agencyId?: string;
//事業者名
agencyName?: string;
//売上日
earningDate?: string;
//請求結果
result?: string;
//請求金額
amount: number = 0;
//NGフラグ
ngFlag: number = 0;
//支払要求
payRequest: number = 0;
//取消依頼
cancelRequest: number = 0;
detailList?: ClaimDetailModel[];
}
export class ClaimDetailModel {
//路線名
routeName?: string;
//乗車停留所名
getonStopName?: string;
//降車停留所ID
getoffStopId?: string;
//降車停留所名
getoffStopName?: string;
//乗車日時
getonDt?: string;
//降車日時
getoffDt?: string;
//請求金額
amount: number = 0;
//料金
price: number = 0;
}
\ No newline at end of file
......@@ -22,4 +22,10 @@ export class CreditCardModel {
//CVC
cvc: string = "";
//拒否リスト状態
denyStatus: number = 0;
//拒否リスト削除依頼
deleteDeny: number = 1;
}
\ No newline at end of file
/**
* 乗降履歴情報
*/
export class HistoryModel {
//乗降日時
getonoffDt?: string;
//乗車/降車
kind?: string;
//停留所ID
stopId?: string;
//停留所名
stopName?: string;
//運賃
fare?: number;
//ステータス
status?: number;
}
\ No newline at end of file
/**
* 払戻情報
*/
export class RefundModel {
//乗車停留所
getonStopId?: string;
//降車停留所
getoffStopId?: string;
//購入金額
purchaseAmount?: number;
//通常運賃
standardFare?: number;
//使用日数
usedDays?: number;
//払戻手数料
refundFee?: number;
//払戻額
refundAmount?: number;
}
\ No newline at end of file
/**
* 利用者情報
*/
export class UserInfoModel {
//利用者ID
customerId?: string;
//氏名
name?: string;
//フリガナ
nameKana?: string;
//電話番号
phoneNumber?: string;
//メールアドレス
email?: string;
//パスワード
password?: string;
}
\ No newline at end of file
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PassChangePage } from './pass-change.page';
const routes: Routes = [
{
path: '',
component: PassChangePage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PassChangePageRoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { PassChangePageRoutingModule } from './pass-change-routing.module';
import { PassChangePage } from './pass-change.page';
import { HeaderComponent } from '../common/header/header.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
PassChangePageRoutingModule,
HeaderComponent
],
declarations: [PassChangePage]
})
export class PassChangePageModule { }
<ion-header [translucent]="true">
<app-header [mode]="1" (clickClose)="onClickClose()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid class="ion-no-padding" style="margin-top:20px;">
<ion-row>
<ion-col style="margin-left:20px;">
<ion-label>路線</ion-label>&nbsp;
<ion-label>{{commuterPassModel?.routeName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>使用期間</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-label>{{commuterPassModel?.useTermName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>料金区分</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-label>{{commuterPassModel?.privateRangeName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>使用開始日</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-label>{{commuterPassModel?.startDate}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>乗車区間(変更前)</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-label>{{commuterPassModel?.getonStopName}}~{{commuterPassModel?.getoffStopName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-top:10px;">
<ion-item>
<ion-select label="乗車停留所" [(ngModel)]="getonStopId" (ionChange)="onChangeGetOn($event)">
@for (kv of stopList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-top:10px;">
<ion-item>
<ion-select label="区間" [(ngModel)]="getoffStopId" (ionChange)="onChangeGetOff($event)">
@for (kv of stopList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>購入金額</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-top:10px;">
<ion-label style="margin-right:20px;">{{purchasePrice|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>払戻金額</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-top:10px;">
<ion-label style="margin-right:20px;">{{refundPrice|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center" style="margin-top:20px;">
<ion-button id="change" class="common-button rounded">変更</ion-button>
<ion-alert trigger="change" header="選択されているクレジットカードで支払い、または、払い戻ししますが、よろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickChange($event)"></ion-alert>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PassChangePage } from './pass-change.page';
describe('PassChangePage', () => {
let component: PassChangePage;
let fixture: ComponentFixture<PassChangePage>;
beforeEach(() => {
fixture = TestBed.createComponent(PassChangePage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Input, OnInit } from '@angular/core';
import { CommuterPassModel } from '../model/commuter-pass.model';
import { RouteService } from '../services/route.service';
import { PassService } from '../services/pass.service';
/**
* 定期券区間変更画面
*/
@Component({
selector: 'app-pass-change',
templateUrl: './pass-change.page.html',
styleUrls: ['./pass-change.page.scss'],
})
export class PassChangePage implements OnInit {
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//カード番号
cardNumber?: string;
//定期券情報
commuterPassModel?: CommuterPassModel;
//停留所一覧
stopList?: Map<string, string>;
//変更後乗車停留所ID
getonStopId?: string;
//変更後降車停留所ID
getoffStopId?: string;
//購入金額
purchasePrice: number = 0;
//払戻金額
refundPrice: number = 0;
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param passService 定期券サービス
*/
constructor(private routeService: RouteService, private passService: PassService) {
this.cardNumber = routeService.cardNumber;
this.commuterPassModel = routeService.commuterPassModel;
}
/**
* 初期化
*/
ngOnInit(): void {
//停留所一覧
if (this.commuterPassModel) {
this.stopList = this.passService.getStopList(this.commuterPassModel?.agencyId, this.commuterPassModel?.routeId);
this.getonStopId = this.commuterPassModel.getonStopId;
this.getoffStopId = this.commuterPassModel.getoffStopId;
this.purchasePrice = this.passService.calcPassAmount(this.commuterPassModel.agencyId, this.commuterPassModel.routeId, this.commuterPassModel.useTermId, this.commuterPassModel.priceRangeId, this.getonStopId, this.getoffStopId);
this.refundPrice = this.passService.calcRefundAmount(this.commuterPassModel.agencyId, this.commuterPassModel.routeId, this.commuterPassModel.startDate, this.commuterPassModel.useTermId, this.commuterPassModel.priceRangeId, this.commuterPassModel.getonStopId, this.commuterPassModel.getoffStopId, this.purchasePrice);
}
}
/**
* 閉じる
*/
onClickClose(): void {
this.routeService.navigatePassSelect(this.cardNumber);
}
/**
* 定期券区間変更
*/
onClickChange(event: any): void {
if (event.detail.role === 'confirm') {
//定期券区間変更
if (this.commuterPassModel) {
this.commuterPassModel.getonStopId = this.getonStopId ? this.getonStopId : "";
this.commuterPassModel.getoffStopId = this.getoffStopId ? this.getoffStopId : "";
this.passService.change(this.commuterPassModel);
}
}
this.routeService.navigatePassSelect(this.cardNumber);
}
/**
* 乗車停留所選択
* @param event イベント情報
*/
onChangeGetOn(event: any): void {
if (this.commuterPassModel) {
this.purchasePrice = this.passService.calcPassAmount(this.commuterPassModel.agencyId, this.commuterPassModel.routeId, this.commuterPassModel.useTermId, this.commuterPassModel.priceRangeId, event.target.value, this.getoffStopId);
}
}
/**
* 降車停留所選択
* @param event イベント情報
*/
onChangeGetOff(event: any): void {
if (this.commuterPassModel) {
this.purchasePrice = this.passService.calcPassAmount(this.commuterPassModel.agencyId, this.commuterPassModel.routeId, this.commuterPassModel.useTermId, this.commuterPassModel.priceRangeId, this.getonStopId, event.target.value);
}
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PassContinuePage } from './pass-continue.page';
const routes: Routes = [
{
path: '',
component: PassContinuePage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PassContinuePageRoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { PassContinuePageRoutingModule } from './pass-continue-routing.module';
import { PassContinuePage } from './pass-continue.page';
import { HeaderComponent } from '../common/header/header.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
PassContinuePageRoutingModule,
HeaderComponent
],
declarations: [PassContinuePage]
})
export class PassContinuePageModule { }
<ion-header [translucent]="true">
<app-header [mode]="1" (clickClose)="onClickClose()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid class="ion-no-padding" style="margin-top:20px;">
<ion-row>
<ion-col style="margin-left:20px;">
<ion-label>路線</ion-label>&nbsp;
<ion-label>{{commuterPassModel?.routeName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-top:10px;">
<ion-item>
<ion-select label="使用期間" [(ngModel)]="useTermId" (ionChange)="onChangeTerm($event)">
@for (kv of useTermList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>料金区分</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-label>{{commuterPassModel?.privateRangeName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:15px;">
<ion-label>使用開始日</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-datetime-button datetime="datetime"></ion-datetime-button>
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime" presentation="date" [(ngModel)]="startDate"></ion-datetime>
</ng-template>
</ion-modal>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>乗車区間</ion-label>
</ion-col>
<ion-col style="margin-top:10px;">
<ion-label>{{commuterPassModel?.getonStopName}}~{{commuterPassModel?.getoffStopName}}</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>支払金額</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-right:20px;margin-top:10px;">
<ion-label>{{price|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center" style="margin-top:20px;">
<ion-button id="continue" class="common-button rounded">継続</ion-button>
<ion-alert trigger="continue" header="選択されているクレジットカードで支払いをしてよろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickContinue($event)"></ion-alert>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PassContinuePage } from './pass-continue.page';
describe('PassContinuePage', () => {
let component: PassContinuePage;
let fixture: ComponentFixture<PassContinuePage>;
beforeEach(() => {
fixture = TestBed.createComponent(PassContinuePage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { RouteService } from '../services/route.service';
import { CommuterPassModel } from '../model/commuter-pass.model';
import { PassService } from '../services/pass.service';
/**
* 定期券継続画面
*/
@Component({
selector: 'app-pass-continue',
templateUrl: './pass-continue.page.html',
styleUrls: ['./pass-continue.page.scss'],
})
export class PassContinuePage implements OnInit {
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//カード番号
cardNumber?: string;
//定期券情報
commuterPassModel?: CommuterPassModel;
//使用期間一覧
useTermList?: Map<string, string>;
//使用期間ID
useTermId?: string;
//使用開始日
startDate?: string;
//金額
price: number = 0;
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param passService 定期券サービス
*/
constructor(private routeService: RouteService, private passService: PassService) {
this.cardNumber = routeService.cardNumber;
this.commuterPassModel = routeService.commuterPassModel;
}
/**
* 初期化
*/
ngOnInit(): void {
//使用期間一覧
if (this.commuterPassModel) {
this.useTermList = this.passService.getUseTermList(this.commuterPassModel?.agencyId);
this.useTermId = this.commuterPassModel.useTermId;
this.price = this.passService.calcPassAmount(this.commuterPassModel.agencyId, this.commuterPassModel.routeId, this.useTermId, this.commuterPassModel.priceRangeId, this.commuterPassModel.getonStopId, this.commuterPassModel.getoffStopId);
}
}
/**
* 閉じる
*/
onClickClose(): void {
this.routeService.navigatePassSelect(this.cardNumber);
}
/**
* 定期券継続
*/
onClickContinue(event: any): void {
if (event.detail.role === 'confirm') {
//定期券継続
if (this.commuterPassModel) {
this.commuterPassModel.useTermId = this.useTermId ? this.useTermId : "";
this.commuterPassModel.startDate = this.startDate ? this.startDate : "";
this.passService.continue(this.commuterPassModel);
}
}
this.routeService.navigatePassSelect(this.cardNumber);
}
/**
* 使用期間選択
* @param event イベント情報
*/
onChangeTerm(event: any): void {
if (this.commuterPassModel) {
this.price = this.passService.calcPassAmount(this.commuterPassModel.agencyId, this.commuterPassModel.routeId, event.target.value, this.commuterPassModel.priceRangeId, this.commuterPassModel.getonStopId, this.commuterPassModel.getoffStopId);
}
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PassRefundPage } from './pass-refund.page';
const routes: Routes = [
{
path: '',
component: PassRefundPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PassRefundPageRoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { PassRefundPageRoutingModule } from './pass-refund-routing.module';
import { PassRefundPage } from './pass-refund.page';
import { HeaderComponent } from '../common/header/header.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
PassRefundPageRoutingModule,
HeaderComponent
],
declarations: [PassRefundPage]
})
export class PassRefundPageModule { }
<ion-header [translucent]="true">
<app-header [mode]="1" (clickClose)="onClickClose()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid class="ion-no-padding" style="margin-top:20px;">
<ion-row>
<ion-col style="margin-left:20px;">
<ion-label>乗車区間</ion-label>
</ion-col>
<ion-col>
<ion-label>{{commuterPassModel?.getonStopName}}~{{commuterPassModel?.getoffStopName}} </ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>購入金額</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-right:20px;margin-top:10px;">
<ion-label>{{purchaseAmount|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>普通運賃</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-right:20px;margin-top:10px;">
<ion-label>{{standardFare|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>使用日数</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-right:20px;margin-top:10px;">
<ion-label>{{usedDays}}日</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>払戻手数料</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-right:20px;margin-top:10px;">
<ion-label>{{refundFee|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:20px;margin-top:10px;">
<ion-label>払戻金額</ion-label>
</ion-col>
<ion-col class="ion-text-right" style="margin-right:20px;margin-top:10px;">
<ion-label>{{refundAmount|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center" style="margin-top:20px;">
<ion-button id="refund" class="common-button rounded">払戻</ion-button>
<ion-alert trigger="refund" header="選択されているクレジットカードで払い戻ししてよろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickRefund($event)"></ion-alert>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PassRefundPage } from './pass-refund.page';
describe('PassRefundPage', () => {
let component: PassRefundPage;
let fixture: ComponentFixture<PassRefundPage>;
beforeEach(() => {
fixture = TestBed.createComponent(PassRefundPage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { CommuterPassModel } from '../model/commuter-pass.model';
import { RouteService } from '../services/route.service';
import { PassService } from '../services/pass.service';
import { RefundModel } from '../model/refund.model';
/**
* 定期券払戻画面
*/
@Component({
selector: 'app-pass-refund',
templateUrl: './pass-refund.page.html',
styleUrls: ['./pass-refund.page.scss'],
})
export class PassRefundPage implements OnInit {
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//カード番号
cardNumber?: string;
//定期券情報
commuterPassModel?: CommuterPassModel;
//購入金額
purchaseAmount: number = 0;
//普通運賃
standardFare: number = 0;
//使用日数
usedDays: number = 0;
//払戻手数料
refundFee: number = 0;
//払戻金額
refundAmount: number = 0;
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param passService 定期券サービス
*/
constructor(private routeService: RouteService, private passService: PassService) {
this.cardNumber = routeService.cardNumber;
this.commuterPassModel = routeService.commuterPassModel;
}
/**
* 初期化
*/
ngOnInit(): void {
if (this.commuterPassModel && this.commuterPassModel.commuterPassId) {
let model: RefundModel = this.passService.getRefund(this.commuterPassModel.commuterPassId);
this.purchaseAmount = model.purchaseAmount ? model.purchaseAmount : 0;
this.standardFare = model.standardFare ? model.standardFare : 0;
this.usedDays = model.usedDays ? model.usedDays : 0;
this.refundFee = model.refundFee ? model.refundFee : 0;
this.refundAmount = model.refundAmount ? model.refundAmount : 0;
}
}
/**
* 閉じる
*/
onClickClose(): void {
this.routeService.navigatePassSelect(this.cardNumber);
}
/**
* 払い戻し
*/
onClickRefund(event: any): void {
if (event.detail.role === 'confirm') {
//定期券払戻
if (this.commuterPassModel) {
this.passService.refund(this.commuterPassModel);
}
}
this.routeService.navigatePassSelect(this.cardNumber);
}
}
......@@ -9,6 +9,7 @@ import { PassRegistPageRoutingModule } from './pass-regist-routing.module';
import { PassRegistPage } from './pass-regist.page';
import { HeaderComponent } from '../common/header/header.component';
import { PassInfoComponent } from '../pass-select/pass-info/pass-info.component';
@NgModule({
imports: [
......@@ -16,7 +17,8 @@ import { HeaderComponent } from '../common/header/header.component';
FormsModule,
IonicModule,
PassRegistPageRoutingModule,
HeaderComponent
HeaderComponent,
PassInfoComponent
],
declarations: [PassRegistPage]
})
......
......@@ -3,90 +3,14 @@
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid>
<ion-row>
<ion-col>
<ion-item>
<ion-select label="路線" [(ngModel)]="routeId" (ionChange)="onChangeRoute($event)">
@for (kv of routeList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-select label="使用期間" [(ngModel)]="useTermId" (ionChange)="onChangeTerm($event)">
@for (kv of useTermList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-select label="料金区分" [(ngModel)]="priceRangeId" (ionChange)="onChangeRange($event)">
@for (kv of priceRangeList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col style="margin-left:16px;">
<ion-label>使用開始日</ion-label>
</ion-col>
<ion-col>
<ion-datetime-button datetime="datetime"></ion-datetime-button>
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime" presentation="date" [(ngModel)]="startDate"
[showDefaultButtons]="true"></ion-datetime>
</ng-template>
</ion-modal>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-select label="乗車停留所" [(ngModel)]="getonStopId" (ionChange)="onChangeGetOn($event)">
@for (kv of stopList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-select label="区間" [(ngModel)]="getoffStopId" (ionChange)="onChangeGetOff($event)">
@for (kv of stopList|keyvalue;track kv.key) {
<ion-select-option [value]="kv.key">{{kv.value}}</ion-select-option>
}
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-label style="margin-left:16px;">支払金額</ion-label>
</ion-col>
<ion-col class="ion-text-right">
<ion-label style="margin-right:20px;">{{price|number}}円</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<ion-button id="addpass" class="common-button rounded" style="margin-top:20px;">追加</ion-button>
<ion-alert trigger="addpass" header="選択されているクレジットカードで支払いをしてよろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickAdd($event)"></ion-alert>
</ion-col>
</ion-row>
</ion-grid>
<div style="margin-left:10px;margin-right:10px;">
@for(model of commuterPassList;track model.routeId) {
<div style="margin-top:10px;">
<app-pass-info [mode]="1" [model]="model"></app-pass-info>
</div>
}
</div>
<div style="margin-top:20px;text-align:center;">
<ion-button class="common-button" style="margin-top:20px;" (click)="onClickAdd($event)">追加</ion-button>
</div>
</ion-content>
\ No newline at end of file
......@@ -12,43 +12,8 @@ import { PassService } from '../services/pass.service';
styleUrls: ['./pass-regist.page.scss'],
})
export class PassRegistPage implements OnInit {
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
//路線一覧
routeList?: Map<string, string>;
//使用期間一覧
useTermList?: Map<string, string>;
//料金区分一覧
priceRangeList?: Map<string, string>;
//停留所一覧
stopList?: Map<string, string>;
//路線
routeId?: string;
//使用期間
useTermId?: string;
//料金区分
priceRangeId?: string;
//使用開始日
startDate?: string;
//乗車停留所
getonStopId?: string;
//区間
getoffStopId?: string;
//支払金額
price: number = 0;
//事業者ID
agencyId: string = "";
//定期券一覧
commuterPassList?: CommuterPassModel[];
/**
* コンストラクタ
......@@ -61,90 +26,24 @@ export class PassRegistPage implements OnInit {
* 初期化
*/
ngOnInit(): void {
this.passService.getListNoCard().subscribe((ret: CommuterPassModel[]) => {
this.commuterPassList = ret;
});
//路線一覧
//TODO 事業者IDはどうやって決める?
this.routeList = this.passService.getRouteList(this.agencyId);
this.routeId = this.routeList.keys().next().value;
//使用期間一覧
this.useTermList = this.passService.getUseTermList(this.agencyId);
this.useTermId = this.useTermList.keys().next().value;
//料金区分一覧
this.priceRangeList = this.passService.getPriceRangeList(this.agencyId);
this.priceRangeId = this.priceRangeList.keys().next().value;
//停留所一覧
this.stopList = this.passService.getStopList(this.agencyId, this.routeList.values().next().value);
this.getonStopId = this.stopList.keys().next().value;
this.getoffStopId = this.stopList.keys().next().value;
}
/**
* 路線選択
* @param event イベント情報
*/
onChangeRoute(event: any): void {
this.stopList = this.passService.getStopList(this.agencyId, event.target.value);
this.price = this.passService.calcPassAmount(this.agencyId, event.target.value, this.useTermId, this.priceRangeId, this.getonStopId, this.getoffStopId);
}
/**
* 使用期間選択
* @param event イベント情報
*/
onChangeTerm(event: any): void {
this.price = this.passService.calcPassAmount(this.agencyId, this.routeId, event.target.value, this.priceRangeId, this.getonStopId, this.getoffStopId);
}
/**
* 料金区分選択
* @param event イベント情報
*/
onChangeRange(event: any): void {
this.price = this.passService.calcPassAmount(this.agencyId, this.routeId, this.useTermId, event.target.value, this.getonStopId, this.getoffStopId);
}
/**
* 乗車停留所選択
* @param event イベント情報
*/
onChangeGetOn(event: any): void {
this.price = this.passService.calcPassAmount(this.agencyId, this.routeId, this.useTermId, this.priceRangeId, event.target.value, this.getoffStopId);
}
/**
* 降車停留所選択
* @param event イベント情報
*/
onChangeGetOff(event: any): void {
this.price = this.passService.calcPassAmount(this.agencyId, this.routeId, this.useTermId, this.priceRangeId, this.getonStopId, event.target.value);
}
/**
* 閉じる
*/
* 閉じる
*/
onClickClose(): void {
this.routeService.navigatePassSelect(this.routeService.cardNumber);
}
/**
* 追加
* @param event イベント情報
*/
onClickAdd(event: any): void {
if (event.detail.role === 'confirm') {
//定期券登録
let model: CommuterPassModel = new CommuterPassModel();
model.tokenId = this.routeService.tokenId;
model.routeId = this.routeId ? this.routeId : "";
model.startDate = this.startDate ? this.startDate : "";
model.useTermId = this.useTermId ? this.useTermId : "";
model.priceRangeId = this.priceRangeId ? this.priceRangeId : "";
model.getonStopId = this.getonStopId ? this.getonStopId : "";
model.getoffStopId = this.getoffStopId ? this.getoffStopId : "";
this.passService.regist(model);
}
this.routeService.navigatePassSelect(this.routeService.cardNumber);
}
}
<div class="rounded border">
<ion-grid class="ion-no-padding">
<ion-row>
@if (mode === 1) {
<ion-col size="auto">
<ion-checkbox class="form-check-input" style="margin-top:80px;margin-left:10px;margin-right:10px;"
(change)="onChangeSelect($event)"></ion-checkbox>
</ion-col>
}
<ion-col>
<ion-grid class="ion-no-padding">
<ion-row>
......@@ -42,17 +48,18 @@
</ion-row>
</ion-grid>
</ion-col>
@if (mode === 0) {
<ion-col style="vertical-align: top;padding-top:20px;padding-right:10px;" size="auto">
<ion-grid class="ion-no-padding">
<ion-row>
<ion-col size="auto">
<div class="common-link" (click)="onClickChange()">変更</div>
<div class="common-link" (click)="onClickContinue()">継続</div>
<div class="common-link" (click)="onClickRefund()">払戻</div>
<div class="common-link" (click)="onClickCancel()">解除</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-col>
}
</ion-row>
</ion-grid>
</div>
\ No newline at end of file
......@@ -16,9 +16,8 @@ import { CommuterPassModel } from 'src/app/model/commuter-pass.model';
})
export class PassInfoComponent {
@Input() model?: CommuterPassModel;
@Output() clickChange: EventEmitter<void> = new EventEmitter();
@Output() clickContinue: EventEmitter<void> = new EventEmitter();
@Output() clickRefund: EventEmitter<void> = new EventEmitter();
@Input() mode?: number;
@Output() clickCancel: EventEmitter<void> = new EventEmitter();
/**
* コンストラクタ
......@@ -26,23 +25,13 @@ export class PassInfoComponent {
constructor() { }
/**
* 変更
* 解除
*/
onClickChange(): void {
this.clickChange.emit();
onClickCancel(): void {
this.clickCancel.emit();
}
/**
* 継続
*/
onClickContinue(): void {
this.clickContinue.emit();
}
onChangeSelect(event: any): void {
/**
* 払戻
*/
onClickRefund(): void {
this.clickRefund.emit();
}
}
......@@ -17,8 +17,7 @@
<div style="margin-left:10px;margin-right:10px;">
@for(model of commuterPassList;track model.routeId) {
<div style="margin-top:10px;">
<app-pass-info [model]="model" (clickChange)="onClickChange(model)" (clickContinue)="onClickContinue(model)"
(clickRefund)="onClickRefund(model)"></app-pass-info>
<app-pass-info [mode]="0" [model]="model" (clickCancel)="onClickCancel(model)"></app-pass-info>
</div>
}
</div>
......
......@@ -29,9 +29,12 @@ export class PassSelectPage implements OnInit {
/**
* 初期化
*/
ngOnInit() {
ngOnInit(): void {
if (this.routeService.tokenId) {
this.commuterPassList = this.passService.getList(this.routeService.tokenId);
//this.commuterPassList = this.passService.getList(this.routeService.tokenId);
this.passService.getList(this.routeService.tokenId).subscribe((ret: CommuterPassModel[]) => {
this.commuterPassList = ret;
});
}
}
......@@ -42,34 +45,18 @@ export class PassSelectPage implements OnInit {
this.routeService.navigateCardSelect();
}
/**
* 定期券区間変更
* @param model 定期券情報
*/
onClickChange(model: CommuterPassModel) {
this.routeService.navigatePassChange(model);
}
/**
* 定期券継続
* @param model 定期券情報
*/
onClickContinue(model: CommuterPassModel) {
this.routeService.navigatePassContinue(model);
}
/**
* 定期券払戻
* @param model 定期券情報
*/
onClickRefund(model: CommuterPassModel) {
this.routeService.navigatePassRefund(model);
onClickCancel(model: CommuterPassModel): void {
}
/**
* 定期券登録
*/
onClickAddPass() {
onClickAddPass(): void {
this.routeService.navigatePassRegist();
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PasswordUpdatePage } from './password-update.page';
const routes: Routes = [
{
path: '',
component: PasswordUpdatePage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PasswordUpdatePageRoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { PasswordUpdatePageRoutingModule } from './password-update-routing.module';
import { PasswordUpdatePage } from './password-update.page';
import { HeaderComponent } from '../common/header/header.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
PasswordUpdatePageRoutingModule,
HeaderComponent
],
declarations: [PasswordUpdatePage]
})
export class PasswordUpdatePageModule { }
<ion-header [translucent]="true">
<app-header [mode]="1" (clickClose)="onClickClose()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="email" label="メールアドレス" [value]="email"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="password" label="パスワード" [value]="password">
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
</ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-right">
<ion-label style="margin-right:20px;">
<span style="font-size:12px;">※パスワードは、8文字以上としてください</span>
</ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<ion-button class="common-button rounded" style="margin-top:20px;" (click)="onClickUpdate()">更新</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PasswordUpdatePage } from './password-update.page';
describe('PasswordUpdatePage', () => {
let component: PasswordUpdatePage;
let fixture: ComponentFixture<PasswordUpdatePage>;
beforeEach(() => {
fixture = TestBed.createComponent(PasswordUpdatePage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component } from '@angular/core';
import { RouteService } from '../services/route.service';
import { UserService } from '../services/user.service';
/**
* パスワード更新画面
*/
@Component({
selector: 'app-password-update',
templateUrl: './password-update.page.html',
styleUrls: ['./password-update.page.scss'],
})
export class PasswordUpdatePage {
//メールアドレス
email?: string;
//パスワード
password?: string;
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param userService 利用者サービス
*/
constructor(private routeService: RouteService, private userService: UserService) { }
/**
* 閉じる
*/
onClickClose(): void {
this.routeService.navigateHome();
}
/**
* 更新
*/
onClickUpdate(): void {
//パスワード更新
this.userService.changePassword(this.email, this.password);
this.routeService.navigateHome();
}
}
import { CustomDatePipe } from './custom-date.pipe';
describe('CustomDatePipe', () => {
it('create an instance', () => {
const pipe = new CustomDatePipe();
expect(pipe).toBeTruthy();
});
});
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'customDate',
standalone: true
})
export class CustomDatePipe implements PipeTransform {
/**
* YYYYMMDD→YYYY/MM/DD変換
* @param value YYYYMMDD
* @returns YYYY/MM/DD
*/
transform(value?: string): string {
if (!value) {
return "";
}
const year = value.substring(0, 4);
const month = value.substring(4, 6);
const day = value.substring(6);
return year + "/" + month + "/" + day;
}
}
import { CustomDatetimePipe } from './custom-datetime.pipe';
describe('CustomDatetimePipe', () => {
it('create an instance', () => {
const pipe = new CustomDatetimePipe();
expect(pipe).toBeTruthy();
});
});
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'customDatetime',
standalone: true
})
export class CustomDatetimePipe implements PipeTransform {
/**
* YYYYMMDDHHMISS→YYYY/MM/DD HH:MI:SS変換
* @param value YYYYMMDDHHMISS→YYYY
* @returns YYYY/MM/DD HH:MI:SS
*/
transform(value?: string): string {
if (!value) {
return "";
}
const year = value.substring(0, 4);
const month = value.substring(4, 6);
const day = value.substring(6, 8);
const hour = value.substring(8, 10);
const min = value.substring(10, 12);
const sec = value.substring(12);
return year + "/" + month + "/" + day + " " + hour + ":" + min + ":" + sec;
}
}
import { Injectable } from '@angular/core';
import { CreditCardModel } from '../model/credit-card.model';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
/**
* クレジットカードサービス
......@@ -8,30 +10,19 @@ import { CreditCardModel } from '../model/credit-card.model';
providedIn: 'root'
})
export class CardService {
readonly cardUrl = './data/card.json';
/**
* コンストラクタ
*/
constructor() { }
constructor(private http: HttpClient) { }
/**
* クレジットカード情報一覧取得
* @param customerId 利用者ID
*/
getList(customerId?: string): CreditCardModel[] {
//TODO
let cardList = new Array();
for (let i = 0; i < 2; i++) {
let model: CreditCardModel = new CreditCardModel();
let value = 1234 + i;
model.tokenId = String(value);
model.cardKind = i;
model.cardNumber = String(value);
model.cardOwner = "TARO YAMADA";
model.cardYear = "2023";
model.cardMonth = "02";
cardList.push(model);
}
return cardList;
getList(customerId?: string): Observable<CreditCardModel[]> {
return this.http.get<CreditCardModel[]>(this.cardUrl);
}
/**
......@@ -39,7 +30,7 @@ export class CardService {
* @param customerId 利用者ID
* @param model クレジットカード情報
*/
regist(customerId?: string, model?: CreditCardModel) {
regist(customerId?: string, model?: CreditCardModel): void {
//TODO
}
......
import { TestBed } from '@angular/core/testing';
import { LoginService } from './login.service';
import { ClaimlistService } from './claimlist.service';
describe('LoginService', () => {
let service: LoginService;
describe('ClaimlistService', () => {
let service: ClaimlistService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LoginService);
service = TestBed.inject(ClaimlistService);
});
it('should be created', () => {
......
import { Injectable } from '@angular/core';
import { ClaimListModel } from '../model/claim-list.model';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
/**
* 請求一覧サービス
*/
@Injectable({
providedIn: 'root'
})
export class ClaimlistService {
readonly claimUrl = './data/claimlist.json';
/**
* コンストラクタ
*/
constructor(private http: HttpClient) { }
/**
* 請求一覧取得
* @param customerId 利用者ID
* @return 請求一覧
*/
getList(customerId: string): Observable<ClaimListModel[]> {
return this.http.get<ClaimListModel[]>(this.claimUrl);
}
/**
* 拒否リスト削除依頼
* @param list 依頼対象
*/
reqDelete(list: ClaimListModel[]): void {
//TODO
}
}
import { TestBed } from '@angular/core/testing';
import { DenylistService } from './denylist.service';
describe('DenylistService', () => {
let service: DenylistService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DenylistService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { DenyListModel } from '../model/deny-list.model';
/**
* 拒否リストサービス
*/
@Injectable({
providedIn: 'root'
})
export class DenylistService {
/**
* コンストラクタ
*/
constructor() { }
/**
* 拒否リスト取得
* @param customerId 利用者ID
*/
getList(customerId: string): DenyListModel[] {
//TODO
let denyList = new Array();
for (let i = 0; i < 4; i++) {
let denyListModel = new DenyListModel();
let str = String(i);
denyListModel.getonStopId = str;
denyListModel.getonStopName = "XXXX停留所";
denyListModel.getoffStopName = "YYYYY停留所";
denyListModel.getonDt = "2024/06/20 10:00:01";
denyListModel.getoffDt = "2024/06/20 10:30:02";
denyListModel.amount = 1000;
denyList.push(denyListModel);
}
return denyList;
}
/**
* 拒否リスト削除依頼
* @param list 依頼対象
*/
reqDelete(list: DenyListModel[]): void {
//TODO
}
}
import { TestBed } from '@angular/core/testing';
import { HistoryService } from './history.service';
describe('HistoryService', () => {
let service: HistoryService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(HistoryService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { HistoryModel } from '../model/history.model';
/**
* 乗降履歴サービス
*/
@Injectable({
providedIn: 'root'
})
export class HistoryService {
/**
* コンストラクタ
*/
constructor() { }
/**
* 乗降履歴一覧取得
* @param customerId 利用者ID
* @param searchDate 検索対象日
* @returns 乗降履歴一覧
*/
getHistoryList(customerId: string, searchDate?: string): HistoryModel[] {
//TODO
let historyList = new Array();
for (let i = 0; i < 10; i++) {
let historyModel: HistoryModel = new HistoryModel();
let str = String(i);
if (searchDate) {
let ymd: string[] = searchDate?.split("-");
historyModel.getonoffDt = ymd[0] + "/" + ymd[1] + "/" + ymd[2] + " 17:08:1" + str;
} else {
historyModel.getonoffDt = "2024/07/01 17:08:1" + str;
}
historyModel.stopId = str;
if (i % 2 == 0) {
historyModel.kind = "1";
historyModel.stopName = "XXXX停留所";
historyModel.status = 1;
} else {
historyModel.kind = "2";
historyModel.stopName = "YYYY停留所";
historyModel.fare = 200;
historyModel.status = 1;
}
historyList.push(historyModel);
}
let historyModel: HistoryModel = new HistoryModel();
if (searchDate) {
let ymd: string[] = searchDate?.split("-");
historyModel.getonoffDt = ymd[0] + "/" + ymd[1] + "/" + ymd[2] + " 17:10:10";
} else {
historyModel.getonoffDt = "2024/07/01 17:10:10";
}
historyModel.kind = "1";
historyModel.stopName = "XXXX停留所";
historyModel.status = 0;
historyList.push(historyModel);
return historyList;
}
}
import { Injectable } from '@angular/core';
import { from, Observable } from 'rxjs';
/**
* ログインサービス
*/
@Injectable({
providedIn: 'root'
})
export class LoginService {
/**
* コンストラクタ
*/
constructor() { }
/**
* ログインサービス
* @param email メールアドレス
* @param password パスワード
* @returns ログイン結果
*/
public login(email: string, password: string): boolean {
// TODO
return true;
}
}
import { Injectable } from '@angular/core';
import { CommuterPassModel } from '../model/commuter-pass.model';
import { RefundModel } from '../model/refund.model';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
/**
* 定期券サービス
......@@ -9,250 +10,39 @@ import { RefundModel } from '../model/refund.model';
providedIn: 'root'
})
export class PassService {
readonly passUrl = "./data/pass.json";
/**
* コンストラクタ
*/
constructor() { }
constructor(private http: HttpClient) { }
/**
* 定期一覧取得
* @param tokenId トークンID
* @return 定期一覧
*/
getList(tokenId: string): CommuterPassModel[] {
let commuterPassList = new Array();
for (let i = 0; i < 2; i++) {
let model: CommuterPassModel = new CommuterPassModel();
model.tokenId = tokenId;
model.commuterPassId = String(i + 1);
model.routeId = "00000" + String(i);
model.routeName = "【◯◯◯系統】XXXXX→XXXXX行き";
model.startDate = "2024/07/01";
model.useTermId = "3";
model.useTermName = "3ヶ月";
model.priceRangeId = "1";
model.privateRangeName = "大人";
model.getonStopId = "1";
model.getonStopName = "停留所1";
model.getoffStopId = "5";
model.getoffStopName = "停留所5";
commuterPassList.push(model);
}
return commuterPassList;
}
/**
* 定期券登録
* @param model 定期券情報
*/
regist(model: CommuterPassModel): void {
getList(tokenId: string): Observable<CommuterPassModel[]> {
//TODO
return this.http.get<CommuterPassModel[]>(this.passUrl);
}
/**
* 定期券区間変更
* @param model 定期券情報
* 定期一覧取得
* @return 定期一覧
*/
change(model: CommuterPassModel): void {
getListNoCard(): Observable<CommuterPassModel[]> {
//TODO
return this.http.get<CommuterPassModel[]>(this.passUrl);
}
/**
* 定期券継続
* @param model 定期券情報
*/
continue(model: CommuterPassModel): void {
//TODO
}
/**
* 定期券払戻
* 定期券登録
* @param model 定期券情報
*/
refund(model: CommuterPassModel): void {
//TODO
}
/**
* 路線一覧取得
* @param agencyId 事業者ID
* @returns 路線一覧
*/
getRouteList(agencyId: string): Map<string, string> {
//路線一覧
let routeList = new Map();
for (let i = 0; i < 5; i++) {
let str = String(i + 1);
routeList.set(str, "路線" + str);
}
return routeList;
}
/**
* 使用期間一覧取得
* @param agencyId 事業者ID
* @returns 使用期間一覧
*/
getUseTermList(agencyId: string): Map<string, string> {
let useTermList = new Map();
useTermList.set("1", "1ヶ月");
useTermList.set("3", "3ヶ月");
useTermList.set("6", "6ヶ月");
return useTermList;
}
/**
* 料金区分一覧取得
* @param agencyId 事業者ID
* @returns 料金区分一覧
*/
getPriceRangeList(agencyId: string): Map<string, string> {
let priceRangeList = new Map();
priceRangeList.set("1", "大人");
priceRangeList.set("2", "小児");
priceRangeList.set("3", "学生");
return priceRangeList;
}
/**
* 停留所一覧取得
* @param agencyId 事業者ID
* @param routeId 路線ID
* @returns 停留所一覧
*/
getStopList(agencyId: string, routeId: string): Map<string, string> {
let stopList = new Map();
for (let i = 0; i < 5; i++) {
let str = String(i + 1);
stopList.set(str, "停留所" + str);
}
return stopList;
}
/**
* 定期券料金計算
*
* @param agencyId 事業者ID
* @param routeId 路線ID
* @param useTermId 使用期間
* @param priceRangeId 料金区分
* @param getonStopId 乗車停留所
* @param getoffStopId 降車停留所
*/
calcPassAmount(agencyId: string, routeId?: string, useTermId?: string, priceRangeId?: string, getonStopId?: string, getoffStopId?: string): number {
//TODO
//以下はダミー
//通常運賃
let getonStop = Number(getonStopId);
let getoffStop = Number(getoffStopId);
let unit = (getoffStop - getonStop) >= 0 ? (getoffStop - getonStop) : (getonStop - getoffStop);
unit = unit * 100;
let one = unit * 30 * 0.75;
let three = one * 3 * 0.95;
let six = one * 6 * 0.9;
let ret = 0;
if (useTermId == "1") {
ret = one;
} else if (useTermId == "2") {
ret = three;
} else {
ret = six;
}
if (priceRangeId == "2") {
ret = ret * 0.5;
} else if (priceRangeId == "3") {
ret = ret * 0.6;
}
return Math.floor(ret);
}
/**
* 定期券払戻料金計算
* @param agencyId 事業者ID
* @param routeId 路線ID
* @param startDate 使用開始日
* @param useTermId 使用期間
* @param priceRangeId 料金区分
* @param getonStopId 乗車停留所ID
* @param getoffStopId 降車停留所ID
*/
calcRefundAmount(agencyId: string, routeId?: string, startDate?: string, useTermId?: string, priceRangeId?: string, getonStopId?: string, getoffStopId?: string, purchaseAmount?: number): number {
regist(model: CommuterPassModel): void {
//TODO
//以下はダミー
//通常運賃
let getonStop = Number(getonStopId);
let getoffStop = Number(getoffStopId);
let unit = (getoffStop - getonStop) >= 0 ? (getoffStop - getonStop) : (getonStop - getoffStop);
unit = unit * 100;
if (priceRangeId == "2") {
unit = unit * 0.5;
} else if (priceRangeId == "3") {
unit = unit * 0.6;
}
//残日数計算
let termDay = 0;
let now = new Date();
if (startDate) {
let start = new Date(startDate);
termDay = (now.getTime() - start.getTime()) / 86400000;
}
if (useTermId == "1") {
termDay = 30 - termDay;
} else if (useTermId == "3") {
termDay = 90 - termDay;
} else if (useTermId == "6") {
termDay = 180 - termDay;
}
let amount = 0;
if (purchaseAmount) {
amount = purchaseAmount - (termDay * unit) - 500;
}
amount = amount < 0 ? 0 : amount;
return Math.floor(amount);
}
/**
* 払戻情報取得
* @param commuterPassId 定期券ID
*/
getRefund(commuterPassId: string): RefundModel {
//TODO
//↓以下はダミー
let ret = new RefundModel();
ret.purchaseAmount = this.calcPassAmount("", "", "3", "1", "1", "5");
//通常運賃
let getonStop = 1;
let getoffStop = 5;
let unit = (getoffStop - getonStop) >= 0 ? (getoffStop - getonStop) : (getonStop - getoffStop);
ret.standardFare = unit * 100;
//使用日数計算
let now = new Date();
let start = new Date("2024/07/01");
ret.usedDays = Math.floor((now.getTime() - start.getTime()) / 86400000);
//残日数
let termDay = 90 - ret.usedDays;
//払戻手数料
ret.refundFee = 500;
let amount = ret.purchaseAmount - (termDay * ret.standardFare) - ret.refundFee;
amount = amount < 0 ? 0 : amount;
ret.refundAmount = Math.floor(amount);
return ret;
}
}
......@@ -37,31 +37,6 @@ export class RouteService {
this.router.navigate(['home']);
}
/**
* 利用者登録画面へ遷移
* @param mode 0:登録、1:更新
*/
navigateUserRegist(mode: number, customerId: string) {
this.mode = mode;
this.customerId = customerId;
this.router.navigate(['user-regist']);
}
/**
* パスワード更新画面へ遷移
*/
navigatePasswordUpdate() {
this.router.navigate(['password-update'])
}
/**
* メニュー画面へ遷移
*/
navigateMenu(customerId: string) {
this.customerId = customerId;
this.router.navigate(['menu']);
}
/**
* クレジットカード選択画面へ遷移
*/
......@@ -94,43 +69,9 @@ export class RouteService {
}
/**
* 定期券区間変更画面へ遷移
* @param commuterPassModel 定期券情報
*/
navigatePassChange(commuterPassModel: CommuterPassModel) {
this.commuterPassModel = commuterPassModel;
this.router.navigate(['pass-change']);
}
/**
* 定期券継続画面へ遷移
* @param commuterPassModel 定期券情報
*/
navigatePassContinue(commuterPassModel: CommuterPassModel) {
this.commuterPassModel = commuterPassModel;
this.router.navigate(['pass-continue']);
}
/**
* 定期券払戻画面へ遷移
* @param commuterPassModel 定期券情報
*/
navigatePassRefund(commuterPassModel: CommuterPassModel) {
this.commuterPassModel = commuterPassModel;
this.router.navigate(['pass-refund']);
}
/**
* 乗車履歴画面へ遷移
*/
navigateHistory() {
this.router.navigate(['history']);
}
/**
* 拒否リスト管理画面へ遷移
* 請求一覧画面へ遷移
*/
navigateDenyList() {
this.router.navigate(['deny-list']);
navigateClaimList() {
this.router.navigate(['claim-list']);
}
}
import { TestBed } from '@angular/core/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { UserInfoModel } from '../model/user-info.model';
/**
* 利用者サービス
*/
@Injectable({
providedIn: 'root'
})
export class UserService {
/**
* コンストラクタ
*/
constructor() { }
/**
* 利用者情報取得
* @param customerId 利用者ID
*/
getInfo(customerId: string): UserInfoModel {
let model: UserInfoModel = new UserInfoModel();
//TODO ダミー
model.name = "山田 太郎"
model.nameKana = "ヤマダ タロウ";
model.phoneNumber = "09012345678";
model.email = "yamada_tarou@test.com";
model.password = "password00";
return model;
}
/**
* 利用者情報登録
* @param model 利用者情報
*/
regist(model: UserInfoModel): void {
//TODO
}
/**
* 利用者情報更新
* @param model 利用者情報
*/
update(model: UserInfoModel): void {
//TODO
}
/**
* 利用者退会
* @param customerId 利用者ID
*/
withdraw(customerId: string): void {
//TODO
}
/**
* パスワード変更
* @param email メールアドレス
* @param password パスワード
*/
changePassword(email?: string, password?: string): void {
//TODO
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { UserRegistPage } from './user-regist.page';
const routes: Routes = [
{
path: '',
component: UserRegistPage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class UserRegistPageRoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { UserRegistPageRoutingModule } from './user-regist-routing.module';
import { UserRegistPage } from './user-regist.page';
import { HeaderComponent } from '../common/header/header.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
UserRegistPageRoutingModule,
HeaderComponent
],
declarations: [UserRegistPage]
})
export class UserRegistPageModule { }
<ion-header [translucent]="true">
<app-header [mode]="1" (clickClose)="onClickClose()"></app-header>
</ion-header>
<ion-content [fullscreen]="true">
<ion-grid>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="text" label="氏名" [value]="name" [maxlength]="30"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="text" label="フリガナ" [value]="nameKana" [maxlength]="30"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="tel" label="電話番号" [value]="phoneNumber" [maxlength]="20"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
@if (mode === 0) {
<ion-item>
<ion-input type="email" label="メールアドレス" [value]="email" [maxlength]="50"></ion-input>
</ion-item>
} @else {
<ion-label>メールアドレス</ion-label><ion-label>{{email}}</ion-label>
}
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="password" label="パスワード" [value]="password" [maxlength]="20">
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
</ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-right">
<ion-label style="margin-right:20px;">
<span style="font-size:12px;">※パスワードは、8文字以上としてください</span>
</ion-label>
</ion-col>
</ion-row>
<ion-row>
@if (mode === 0) {
<ion-col class="ion-text-center">
<ion-button id="regist" class="common-button rounded" style="margin-top:20px;">登録</ion-button>
<ion-alert trigger="regist" header="この内容で登録してよろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickRegist($event)"></ion-alert>
</ion-col>
} @else {
<ion-col class="ion-text-center">
<ion-button id="update" class="common-button rounded" style="margin-top:20px;">更新</ion-button>
<ion-alert trigger="update" header="この内容で更新してよろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickUpdate($event)"></ion-alert>
</ion-col>
<ion-col class="ion-text-center">
<ion-button id="withdraw" class="common-button rounded" style="margin-top:20px;">退会</ion-button>
<ion-alert trigger="withdraw" header="退会してよろしいですか?" [buttons]="confirmButtons"
(didDismiss)="onClickWithdraw($event)"></ion-alert>
</ion-col>
}
</ion-row>
</ion-grid>
</ion-content>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserRegistPage } from './user-regist.page';
describe('UserRegistPage', () => {
let component: UserRegistPage;
let fixture: ComponentFixture<UserRegistPage>;
beforeEach(() => {
fixture = TestBed.createComponent(UserRegistPage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { RouteService } from '../services/route.service';
import { UserService } from '../services/user.service';
import { UserInfoModel } from '../model/user-info.model';
/**
* 利用者登録画面
*/
@Component({
selector: 'app-user-regist',
templateUrl: './user-regist.page.html',
styleUrls: ['./user-regist.page.scss'],
})
export class UserRegistPage implements OnInit {
//モード(0:登録、1:更新)
mode: number = 0;
//氏名
name?: string;
//フリガナ
nameKana?: string;
//電話番号
phoneNumber?: string;
//メールアドレス
email?: string;
//パスワード
password?: string;
//利用者ID
customerId?: string;
public confirmButtons = [
{
text: 'いいえ',
role: 'cancel'
},
{
text: 'はい',
role: 'confirm'
},
];
/**
* コンストラクタ
* @param routeService 画面遷移サービス
* @param userService 利用者情報サービス
*/
constructor(private routeService: RouteService, private userService: UserService) {
this.mode = routeService.mode;
this.customerId = routeService.customerId;
}
/**
* 初期処理
*/
ngOnInit(): void {
if (this.customerId) {
let model: UserInfoModel = this.userService.getInfo(this.customerId);
this.name = model.name;
this.nameKana = model.nameKana;
this.phoneNumber = model.phoneNumber;
this.email = model.email;
this.password = model.password;
}
}
/**
* 閉じる
*/
onClickClose(): void {
this.routeService.navigateHome();
}
/**
* 登録
* @param event イベント情報
*/
onClickRegist(event: any): void {
if (event.detail.role === 'confirm') {
//利用者情報登録
let model: UserInfoModel = new UserInfoModel();
model.name = this.name;
model.nameKana = this.nameKana;
model.phoneNumber = this.phoneNumber;
model.email = this.email;
model.password = this.password;
this.userService.regist(model);
}
this.routeService.navigateHome();
}
/**
* 更新
* @param event イベント情報
*/
onClickUpdate(event: any): void {
if (event.detail.role === 'confirm') {
//利用者情報更新
let model: UserInfoModel = new UserInfoModel();
model.customerId = this.customerId;
model.name = this.name;
model.nameKana = this.nameKana;
model.phoneNumber = this.phoneNumber;
model.email = this.email;
model.password = this.password;
this.userService.update(model);
}
this.routeService.navigateHome();
}
/**
* 退会
* @param event イベント情報
*/
onClickWithdraw(event: any): void {
if (event.detail.role === 'confirm') {
//退会
if (this.customerId) {
this.userService.withdraw(this.customerId);
}
}
this.routeService.navigateHome();
}
}
src/assets/icon/mastercard.png

9.2 KB | W: | H:

src/assets/icon/mastercard.png

2.4 KB | W: | H:

src/assets/icon/mastercard.png
src/assets/icon/mastercard.png
src/assets/icon/mastercard.png
src/assets/icon/mastercard.png
  • 2-up
  • Swipe
  • Onion skin
[
{
"tokenId": "00001",
"cardKind": 1,
"cardNumber": "1234",
"cardOwner": "TARO YAMADA",
"cardYear": "2027",
"cardMonth": "02",
"cvc": "",
"denyStatus": 0,
"deleteDeny": 0
},
{
"tokenId": "00002",
"cardKind": 2,
"cardNumber": "5678",
"cardOwner": "HANAKO YAMADA",
"cardYear": "2026",
"cardMonth": "03",
"cvc": "",
"denyStatus": 1,
"deleteDeny": 0
}
]
\ No newline at end of file
[
{
"tokenId": "00001",
"agencyId": "00001",
"agencyName": "XXXXバス",
"earningDate": "20240620",
"amount": 1000,
"result": "承認",
"ngFlag": 0,
"payRequest": 0,
"cancelRequest": 0,
"detailList": [
{
"routeName": "◯◯◯◯線",
"getonStopName": "A停留所",
"getoffStopName": "B停留所",
"getonDt": "20240620100001",
"getoffDt": "20240620103004",
"price": 400
},
{
"routeName": "◯◯◯◯線",
"getonStopName": "B停留所",
"getoffStopName": "C停留所",
"getonDt": "20240621100001",
"getoffDt": "20240621103004",
"price": 600
}
]
},
{
"tokenId": "00002",
"agencyId": "00001",
"agencyName": "XXXXバス",
"processDt": "20240621103002",
"earningDate": "20240621",
"amount": 2000,
"ngFlag": 1,
"payRequest": 0,
"cancelRequest": 0,
"detailList": [
{
"routeName": "◯◯◯◯線",
"getonStopName": "A停留所",
"getoffStopName": "B停留所",
"getonDt": "20240620100001",
"getoffDt": "20240620103004",
"price": 600
},
{
"routeName": "◯◯◯◯線",
"getonStopName": "B停留所",
"getoffStopName": "C停留所",
"getonDt": "20240621100001",
"getoffDt": "20240621103004",
"price": 500
}
]
}
]
\ No newline at end of file
[
{
"tokenId": "00001",
"commuterPassId": "00001",
"agencyId": "00001",
"routeId": "00001",
"routeName": "【◯◯◯系統】XXXXX→XXXXX行き",
"startDate": "2024/07/01",
"useTermId": "3",
"useTermName": "3ヶ月",
"priceRangeId": "1",
"privateRangeName": "大人",
"getonStopId": "1",
"getonStopName": "停留所1",
"getoffStopId": "5",
"getoffStopName": "停留所5"
},
{
"tokenId": "00001",
"commuterPassId": "00002",
"agencyId": "00001",
"routeId": "00002",
"routeName": "【◯◯◯系統】XXXXX→XXXXX行き",
"startDate": "2024/07/02",
"useTermId": "6",
"useTermName": "6ヶ月",
"priceRangeId": "1",
"privateRangeName": "大人",
"getonStopId": "2",
"getonStopName": "停留所2",
"getoffStopId": "7",
"getoffStopName": "停留所7"
}
]
\ No newline at end of file
......@@ -36,19 +36,15 @@
/* @import "@ionic/angular/css/palettes/dark.class.css"; */
@import "@ionic/angular/css/palettes/dark.system.css";
.common-button {
--background: #F19024;
--color: white;
--height: 40px;
--padding-left: 20px;
--padding-right: 20px;
.label-orange {
color: #FC9422;
}
.common-link {
text-decoration: underline;
color: #0CACCD;
.label-blue {
color: #0DACCD;
}
.add-link {
color: #0CACCD;
.label-gray {
color: #828DA4;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment