feat(ui) - funnels - wip
This commit is contained in:
parent
bf509a374d
commit
45e39c8749
6 changed files with 230 additions and 1 deletions
90
frontend/app/mstore/funnelStore.ts
Normal file
90
frontend/app/mstore/funnelStore.ts
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx"
|
||||
import { funnelService } from "App/services"
|
||||
import Funnel, { IFunnel } from "./types/funnel";
|
||||
import Period, { LAST_7_DAYS } from 'Types/app/period';
|
||||
|
||||
export default class FunnelStore {
|
||||
isLoading: boolean = false
|
||||
isSaving: boolean = false
|
||||
list: IFunnel[] = []
|
||||
instance: IFunnel | null = null
|
||||
period: Period = Period({ rangeName: LAST_7_DAYS })
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
fetchFunnels: action,
|
||||
fetchFunnel: action,
|
||||
saveFunnel: action,
|
||||
deleteFunnel: action
|
||||
})
|
||||
}
|
||||
|
||||
fetchFunnels(): Promise<any> {
|
||||
this.isLoading = true
|
||||
return new Promise((resolve, reject) => {
|
||||
funnelService.all()
|
||||
.then(response => {
|
||||
this.list = response
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.isLoading = false
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fetchFunnel(funnelId: string): Promise<any> {
|
||||
this.isLoading = true
|
||||
return new Promise((resolve, reject) => {
|
||||
funnelService.one(funnelId)
|
||||
.then(response => {
|
||||
const _funnel = new Funnel().fromJSON(response)
|
||||
this.instance = _funnel
|
||||
resolve(_funnel)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.isLoading = false
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
saveFunnel(funnel: IFunnel): Promise<any> {
|
||||
this.isSaving = true
|
||||
const wasCreating = !funnel.funnelId
|
||||
return new Promise((resolve, reject) => {
|
||||
funnelService.save(funnel)
|
||||
.then(response => {
|
||||
const _funnel = new Funnel().fromJSON(response)
|
||||
if (wasCreating) {
|
||||
this.list.push(_funnel)
|
||||
}
|
||||
resolve(_funnel)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.isSaving = false
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
deleteFunnel(funnelId: string): Promise<any> {
|
||||
this.isSaving = true
|
||||
return new Promise((resolve, reject) => {
|
||||
funnelService.delete(funnelId)
|
||||
.then(response => {
|
||||
this.list = this.list.filter(funnel => funnel.funnelId !== funnelId)
|
||||
resolve(funnelId)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.isSaving = false
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
45
frontend/app/mstore/types/funnel.ts
Normal file
45
frontend/app/mstore/types/funnel.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import Filter, { IFilter } from "./filter"
|
||||
|
||||
export interface IFunnel {
|
||||
funnelId: string
|
||||
name: string
|
||||
filter: IFilter
|
||||
sessionsCount: number
|
||||
conversionRate: number
|
||||
totalConversations: number
|
||||
lostConversations: number
|
||||
fromJSON: (json: any) => void
|
||||
toJSON: () => any
|
||||
}
|
||||
|
||||
export default class Funnel implements IFunnel {
|
||||
funnelId: string = ''
|
||||
name: string = ''
|
||||
filter: IFilter = new Filter()
|
||||
sessionsCount: number = 0
|
||||
conversionRate: number = 0
|
||||
totalConversations: number = 0
|
||||
lostConversations: number = 0
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
fromJSON(json: any) {
|
||||
this.funnelId = json.funnelId
|
||||
this.name = json.name
|
||||
this.filter = new Filter().fromJson(json.filter)
|
||||
this.sessionsCount = json.sessionsCount
|
||||
this.conversionRate = json.conversionRate
|
||||
return this
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
funnelId: this.funnelId,
|
||||
name: this.name,
|
||||
filter: this.filter.toJson(),
|
||||
sessionsCount: this.sessionsCount,
|
||||
conversionRate: this.conversionRate,
|
||||
}
|
||||
}
|
||||
}
|
||||
18
frontend/app/mstore/types/funnelStage.ts
Normal file
18
frontend/app/mstore/types/funnelStage.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
export default class FunnelStage {
|
||||
dropDueToIssues: number = 0;
|
||||
dropPct: number = 0;
|
||||
operator: string = "";
|
||||
sessionsCount: number = 0;
|
||||
usersCount: number = 0;
|
||||
value: string[] = [];
|
||||
|
||||
fromJSON(json: any) {
|
||||
this.dropDueToIssues = json.dropDueToIssues;
|
||||
this.dropPct = json.dropPct;
|
||||
this.operator = json.operator;
|
||||
this.sessionsCount = json.sessionsCount;
|
||||
this.usersCount = json.usersCount;
|
||||
this.value = json.value;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
12
frontend/app/mstore/types/funnelnsights.ts
Normal file
12
frontend/app/mstore/types/funnelnsights.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import FunnelStage from "./funnelStage";
|
||||
|
||||
export default class FunnelInsights {
|
||||
stages: FunnelStage[] = [];
|
||||
totalDropDueToIssues: number = 0;
|
||||
|
||||
fromJSON(json: any) {
|
||||
this.stages = json.stages.map(stage => new FunnelStage().fromJSON(stage));
|
||||
this.totalDropDueToIssues = json.totalDropDueToIssues;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
62
frontend/app/services/FunnelService.ts
Normal file
62
frontend/app/services/FunnelService.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { IFunnel } from "App/mstore/types/funnel"
|
||||
import APIClient from 'App/api_client';
|
||||
|
||||
export interface IFunnelService {
|
||||
initClient(client?: APIClient)
|
||||
all(): Promise<any[]>
|
||||
one(funnelId: string): Promise<any>
|
||||
save(funnel: IFunnel): Promise<any>
|
||||
delete(funnelId: string): Promise<any>
|
||||
|
||||
fetchInsights(funnelId: string, payload: any): Promise<any>
|
||||
fetchIssues(funnelId: string, payload: any): Promise<any>
|
||||
fetchIssue(funnelId: string, issueId: string): Promise<any>
|
||||
}
|
||||
|
||||
export default class FunnelService implements IFunnelService {
|
||||
private client: APIClient;
|
||||
|
||||
constructor(client?: APIClient) {
|
||||
this.client = client ? client : new APIClient();
|
||||
}
|
||||
|
||||
initClient(client?: APIClient) {
|
||||
this.client = client || new APIClient();
|
||||
}
|
||||
|
||||
all(): Promise<any[]> {
|
||||
return this.client.get('/funnels')
|
||||
.then(response => response.json())
|
||||
.then(response => response.data || []);
|
||||
}
|
||||
|
||||
one(funnelId: string): Promise<any> {
|
||||
return this.client.get(`/funnels/${funnelId}`)
|
||||
.then(response => response.json())
|
||||
}
|
||||
|
||||
save(funnel: IFunnel): Promise<any> {
|
||||
return this.client.post('/funnels', funnel)
|
||||
.then(response => response.json())
|
||||
}
|
||||
|
||||
delete(funnelId: string): Promise<any> {
|
||||
return this.client.delete(`/funnels/${funnelId}`)
|
||||
.then(response => response.json())
|
||||
}
|
||||
|
||||
fetchInsights(funnelId: string, payload: any): Promise<any> {
|
||||
return this.client.post(`/funnels/${funnelId}/insights`, payload)
|
||||
.then(response => response.json())
|
||||
}
|
||||
|
||||
fetchIssues(funnelId: string, payload: any): Promise<any> {
|
||||
return this.client.post(`/funnels/${funnelId}/issues`, payload)
|
||||
.then(response => response.json())
|
||||
}
|
||||
|
||||
fetchIssue(funnelId: string, issueId: string): Promise<any> {
|
||||
return this.client.get(`/funnels/${funnelId}/issues/${issueId}`)
|
||||
.then(response => response.json())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import DashboardService, { IDashboardService } from "./DashboardService";
|
||||
import MetricService, { IMetricService } from "./MetricService";
|
||||
import FunnelService, { IFunnelService } from "./FunnelService";
|
||||
|
||||
export const dashboardService: IDashboardService = new DashboardService();
|
||||
export const metricService: IMetricService = new MetricService();
|
||||
export const metricService: IMetricService = new MetricService();
|
||||
export const funnelService: IFunnelService = new FunnelService();
|
||||
Loading…
Add table
Reference in a new issue