Initial commit
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import type { ItemResponse } from './types'
|
||||
import type { CreateNeedInput } from '../domain/need'
|
||||
|
||||
export interface CriteriaExtractionResult {
|
||||
extractedCriteria: Partial<CreateNeedInput>
|
||||
confidence: number
|
||||
missingFields: string[]
|
||||
assumptions: string[]
|
||||
followUpQuestions: string[]
|
||||
}
|
||||
|
||||
export interface AIServiceProvider {
|
||||
extractCriteria(naturalLanguageInput: string): Promise<CriteriaExtractionResult>
|
||||
generateFollowUp(partialNeed: Partial<CreateNeedInput>): Promise<string[]>
|
||||
}
|
||||
|
||||
const MockupAIServiceProvider: AIServiceProvider = {
|
||||
async extractCriteria(input: string): Promise<CriteriaExtractionResult> {
|
||||
// Deterministic mock extraction — simulates AI parsing
|
||||
return {
|
||||
extractedCriteria: {
|
||||
companyName: 'Unbekannt (bitte bestätigen)',
|
||||
requiredArea: { min: 400, max: 900 },
|
||||
budgetRange: { maxPerSqm: 40, currency: 'CHF' },
|
||||
},
|
||||
confidence: 0.72,
|
||||
missingFields: ['assetType', 'timing', 'preferredLocations'],
|
||||
assumptions: ['Fläche aus Zahlenangabe geschätzt', 'Budget aus Kostennennung abgeleitet'],
|
||||
followUpQuestions: [
|
||||
'Welchen Nutzungstyp suchen Sie (Büro, Retail, Logistik)?',
|
||||
'In welchen Städten oder Regionen suchen Sie?',
|
||||
'Wann möchten Sie spätestens einziehen?',
|
||||
],
|
||||
}
|
||||
},
|
||||
async generateFollowUp(partialNeed: Partial<CreateNeedInput>): Promise<string[]> {
|
||||
const questions: string[] = []
|
||||
if (!partialNeed.assetType) questions.push('Welchen Nutzungstyp suchen Sie?')
|
||||
if (!partialNeed.preferredLocations?.length) questions.push('In welchen Regionen suchen Sie?')
|
||||
if (!partialNeed.timing) questions.push('Was ist Ihr gewünschter Einzugstermin?')
|
||||
if (!partialNeed.budgetRange) questions.push('Was ist Ihr maximales monatliches Budget?')
|
||||
return questions
|
||||
},
|
||||
}
|
||||
|
||||
const provider = MockupAIServiceProvider
|
||||
|
||||
export const aiService = {
|
||||
async extractCriteria(input: string): Promise<ItemResponse<CriteriaExtractionResult>> {
|
||||
const data = await provider.extractCriteria(input)
|
||||
return { data }
|
||||
},
|
||||
async generateFollowUp(partialNeed: Partial<CreateNeedInput>): Promise<ItemResponse<string[]>> {
|
||||
const data = await provider.generateFollowUp(partialNeed)
|
||||
return { data }
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { MockupFutureSignalProvider } from '../provider/MockupFutureSignalProvider'
|
||||
import type { FutureSignalFilters } from '../provider/IFutureSignalProvider'
|
||||
import type { FutureSignal } from '../domain/futureSignal'
|
||||
import type { ListResponse, ItemResponse } from './types'
|
||||
|
||||
const provider = MockupFutureSignalProvider
|
||||
|
||||
export const futureSignalService = {
|
||||
async getAll(filters?: FutureSignalFilters): Promise<ListResponse<FutureSignal>> {
|
||||
const data = await provider.getAll(filters)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async getById(id: string): Promise<ItemResponse<FutureSignal | null>> {
|
||||
const data = await provider.getById(id)
|
||||
return { data }
|
||||
},
|
||||
async getByProperty(propertyId: string): Promise<ListResponse<FutureSignal>> {
|
||||
const data = await provider.getByProperty(propertyId)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async verify(id: string, verifiedBy: string): Promise<ItemResponse<FutureSignal>> {
|
||||
const data = await provider.verify(id, verifiedBy)
|
||||
return { data }
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { ListResponse, ItemResponse } from './types'
|
||||
|
||||
export type ActivityEventType =
|
||||
| 'PROPERTY_CREATED'
|
||||
| 'PROPERTY_UPDATED'
|
||||
| 'MATCH_APPROVED'
|
||||
| 'MATCH_REJECTED'
|
||||
| 'SIGNAL_VERIFIED'
|
||||
| 'NEED_CREATED'
|
||||
| 'REVIEW_REQUESTED'
|
||||
|
||||
export interface ActivityEvent {
|
||||
id: string
|
||||
type: ActivityEventType
|
||||
entityId: string
|
||||
entityType: 'PROPERTY' | 'MATCH' | 'NEED' | 'SIGNAL'
|
||||
performedBy: string
|
||||
organizationId: string
|
||||
notes?: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
const mockActivityLog: ActivityEvent[] = [
|
||||
{ id: 'evt-001', type: 'PROPERTY_CREATED', entityId: 'prop-001', entityType: 'PROPERTY', performedBy: 'admin@ideal-sharing.ch', organizationId: 'org-wincasa', createdAt: '2025-01-10T08:00:00Z' },
|
||||
{ id: 'evt-002', type: 'MATCH_APPROVED', entityId: 'match-003', entityType: 'MATCH', performedBy: 'admin@ideal-sharing.ch', organizationId: 'org-wincasa', notes: 'Starker Match bestätigt', createdAt: '2025-05-10T09:00:00Z' },
|
||||
{ id: 'evt-003', type: 'SIGNAL_VERIFIED', entityId: 'signal-003', entityType: 'SIGNAL', performedBy: 'admin@ideal-sharing.ch', organizationId: 'org-wincasa', createdAt: '2025-05-05T09:00:00Z' },
|
||||
]
|
||||
|
||||
const store = [...mockActivityLog]
|
||||
|
||||
export const governanceService = {
|
||||
async getActivityLog(organizationId?: string): Promise<ListResponse<ActivityEvent>> {
|
||||
const data = organizationId ? store.filter(e => e.organizationId === organizationId) : [...store]
|
||||
return { data: data.sort((a, b) => b.createdAt.localeCompare(a.createdAt)), meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async logEvent(event: Omit<ActivityEvent, 'id' | 'createdAt'>): Promise<ItemResponse<ActivityEvent>> {
|
||||
const data: ActivityEvent = { id: crypto.randomUUID(), ...event, createdAt: new Date().toISOString() }
|
||||
store.push(data)
|
||||
return { data }
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MockupMatchProvider } from '../provider/MockupMatchProvider'
|
||||
import type { MatchFilters } from '../provider/IMatchProvider'
|
||||
import type { Match } from '../domain/match'
|
||||
import type { ListResponse, ItemResponse } from './types'
|
||||
|
||||
const provider = MockupMatchProvider
|
||||
|
||||
export const matchService = {
|
||||
async getAll(filters?: MatchFilters): Promise<ListResponse<Match>> {
|
||||
const data = await provider.getAll(filters)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async getById(id: string): Promise<ItemResponse<Match | null>> {
|
||||
const data = await provider.getById(id)
|
||||
return { data }
|
||||
},
|
||||
async getByNeed(needId: string): Promise<ListResponse<Match>> {
|
||||
const data = await provider.getByNeed(needId)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async getByProperty(propertyId: string): Promise<ListResponse<Match>> {
|
||||
const data = await provider.getByProperty(propertyId)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async approve(id: string, reviewedBy: string): Promise<ItemResponse<Match>> {
|
||||
const data = await provider.approve(id, reviewedBy)
|
||||
return { data }
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MockupNeedProvider } from '../provider/MockupNeedProvider'
|
||||
import type { NeedFilters } from '../provider/INeedProvider'
|
||||
import type { Need, CreateNeedInput, UpdateNeedInput } from '../domain/need'
|
||||
import type { ListResponse, ItemResponse } from './types'
|
||||
|
||||
const provider = MockupNeedProvider
|
||||
|
||||
export const needService = {
|
||||
async getAll(filters?: NeedFilters): Promise<ListResponse<Need>> {
|
||||
const data = await provider.getAll(filters)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async getById(id: string): Promise<ItemResponse<Need | null>> {
|
||||
const data = await provider.getById(id)
|
||||
return { data }
|
||||
},
|
||||
async create(input: CreateNeedInput): Promise<ItemResponse<Need>> {
|
||||
const data = await provider.create(input)
|
||||
return { data }
|
||||
},
|
||||
async update(id: string, input: UpdateNeedInput): Promise<ItemResponse<Need>> {
|
||||
const data = await provider.update(id, input)
|
||||
return { data }
|
||||
},
|
||||
async remove(id: string): Promise<ItemResponse<void>> {
|
||||
await provider.remove(id)
|
||||
return { data: undefined }
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { MockupPropertyProvider } from '../provider/MockupPropertyProvider'
|
||||
import type { PropertyFilters } from '../provider/IPropertyProvider'
|
||||
import type { CreatePropertyInput, UpdatePropertyInput } from '../domain/property'
|
||||
import type { ListResponse, ItemResponse } from './types'
|
||||
import type { Property } from '../domain/property'
|
||||
|
||||
const provider = MockupPropertyProvider
|
||||
|
||||
export const propertyService = {
|
||||
async getAll(filters?: PropertyFilters): Promise<ListResponse<Property>> {
|
||||
const data = await provider.getAll(filters)
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
},
|
||||
async getById(id: string): Promise<ItemResponse<Property | null>> {
|
||||
const data = await provider.getById(id)
|
||||
return { data }
|
||||
},
|
||||
async create(input: CreatePropertyInput): Promise<ItemResponse<Property>> {
|
||||
const data = await provider.create(input)
|
||||
return { data }
|
||||
},
|
||||
async update(id: string, input: UpdatePropertyInput): Promise<ItemResponse<Property>> {
|
||||
const data = await provider.update(id, input)
|
||||
return { data }
|
||||
},
|
||||
async remove(id: string): Promise<ItemResponse<void>> {
|
||||
await provider.remove(id)
|
||||
return { data: undefined }
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export interface ServiceMeta {
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
hasMore: boolean
|
||||
}
|
||||
|
||||
export interface ServiceResponse<T> {
|
||||
data: T
|
||||
meta?: ServiceMeta
|
||||
error?: string | null
|
||||
}
|
||||
|
||||
export type ListResponse<T> = ServiceResponse<T[]>
|
||||
export type ItemResponse<T> = ServiceResponse<T>
|
||||
Reference in New Issue
Block a user