Intranet AppService içerisinde tüm istekler birleştirilecek

This commit is contained in:
Sedat Öztürk 2025-10-28 23:12:06 +03:00
parent b5c61e9a6d
commit e29a924e87
28 changed files with 133 additions and 141 deletions

View file

@ -6,11 +6,12 @@ namespace Kurs.Platform.Public;
public class EventDto
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Type { get; set; }
public string CategoryName { get; set; }
public string TypeName { get; set; }
public DateTime Date { get; set; }
public string Location { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Place { get; set; }
public EventOrganizerDto Organizer { get; set; }
public int Participants { get; set; }
public List<string> Photos { get; set; } = new();

View file

@ -45,7 +45,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
private async Task<List<EventDto>> GetUpcomingEventsAsync()
{
var events = await _eventRepository
.WithDetailsAsync(e => e.Category, e => e.Type, e => e.Photos, e => e.Comments)
.WithDetailsAsync(e => e.Category, e => e.Type, e => e.Category, e => e.Photos, e => e.Comments)
.ContinueWith(t => t.Result.ToList().Where(e => e.isPublished).OrderByDescending(e => e.CreationTime));
var result = new List<EventDto>();
@ -60,11 +60,12 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
var calendarEvent = new EventDto
{
Id = evt.Id.ToString(),
Title = evt.Name,
Name = evt.Name,
Description = evt.Description,
Type = evt.Type?.Name?.ToLowerInvariant() ?? "social",
Date = evt.CreationTime,
Location = evt.Place,
TypeName = evt.Type?.Name,
CategoryName = evt.Category?.Name,
Date = evt.Date,
Place = evt.Place,
Organizer = new EventOrganizerDto
{
Id = employee.Id,
@ -73,7 +74,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
Avatar = employee.Avatar
},
Participants = evt.ParticipantsCount,
Photos = evt.Photos?.Select(p => p.Url).ToList() ?? [],
Photos = [],
Comments = [],
Likes = evt.Likes,
IsPublished = evt.isPublished

View file

@ -12,9 +12,10 @@ public class Event : FullAuditedEntity<Guid>, IMultiTenant
public Guid CategoryId { get; set; }
public Guid TypeId { get; set; }
public DateTime Date { get; set; }
public string Name { get; set; }
public string Place { get; set; }
public string Description { get; set; }
public string Place { get; set; }
public string Status { get; set; }
public Guid EmployeeId { get; set; }

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20251028185430_Initial")]
[Migration("20251028200151_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -3728,6 +3728,9 @@ namespace Kurs.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<DateTime>("Date")
.HasColumnType("datetime2");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");

View file

@ -4343,9 +4343,10 @@ namespace Kurs.Platform.Migrations
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TypeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Date = table.Column<DateTime>(type: "datetime2", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Place = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
Place = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Status = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
EmployeeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ParticipantsCount = table.Column<int>(type: "int", nullable: false),

View file

@ -3725,6 +3725,9 @@ namespace Kurs.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<DateTime>("Date")
.HasColumnType("datetime2");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");

View file

@ -1509,12 +1509,13 @@
{
"CategoryName": "Spor",
"TypeName": "Futbol Turnuvası",
"Date": "2025-11-15T10:00:00",
"Name": "Yaz Futbol Turnuvası 2025",
"Place": "Şirket Kampüsü Spor Alanı",
"Description": "Tüm departmanların katılımıyla düzenlenen geleneksel yaz futbol turnuvası.",
"Place": "Şirket Kampüsü Spor Alanı",
"Status": "Published",
"ParticipantsCount": 64,
"OrganizerEmployeeCode": "EMP-001",
"ParticipantsCount": 64,
"IsPublished": true,
"Likes": 120,
"Photos": [],
@ -1523,12 +1524,13 @@
{
"CategoryName": "Kültür",
"TypeName": "Kültürel Sanat Günü",
"Date": "2025-11-17T10:00:00",
"Name": "Kültür Gezisi: Kapadokya",
"Place": "Kapadokya, Nevşehir",
"Description": "Çalışanlarımıza özel, rehber eşliğinde 2 günlük kültürel gezi.",
"Place": "Kapadokya, Nevşehir",
"Status": "Published",
"ParticipantsCount": 25,
"OrganizerEmployeeCode": "EMP-002",
"ParticipantsCount": 25,
"IsPublished": true,
"Likes": 45,
"Photos": [],
@ -1537,12 +1539,13 @@
{
"CategoryName": "Müzik",
"TypeName": "Caz Akşamı",
"Date": "2025-11-18T10:00:00",
"Name": "Müzik Dinletisi: Jazz Akşamı",
"Place": "Şirket Konferans Salonu",
"Description": "Caz müziğinin en güzel örneklerinin canlı performanslarla sunulacağı özel akşam.",
"Place": "Şirket Konferans Salonu",
"Status": "Published",
"ParticipantsCount": 40,
"OrganizerEmployeeCode": "EMP-003",
"ParticipantsCount": 40,
"IsPublished": true,
"Likes": 85,
"Photos": [],

View file

@ -1538,6 +1538,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
{
CategoryId = category.Id,
TypeId = type.Id,
Date = item.Date,
Name = item.Name,
Place = item.Place,
Description = item.Description,

View file

@ -699,9 +699,10 @@ public class EventSeedDto
{
public string CategoryName { get; set; }
public string TypeName { get; set; }
public DateTime Date { get; set; }
public string Name { get; set; }
public string Place { get; set; }
public string Description { get; set; }
public string Place { get; set; }
public string Status { get; set; }
public string OrganizerEmployeeCode { get; set; }
public int ParticipantsCount { get; set; }

View file

@ -1,7 +1,7 @@
import { EventDto } from '@/proxy/intranet/models'
import { mockEmployees } from './mockEmployees'
import {
Announcement,
CalendarEvent,
Visitor,
Document,
Certificate,
@ -822,15 +822,16 @@ export const mockSocialPosts: SocialPost[] = [
/////////////////////////////////////////////////////////////////////////////////////
///////APP SERVİS YAPILANLAR//////////
export const mockEvents: CalendarEvent[] = [
export const mockEvents: EventDto[] = [
{
id: 'evt1',
title: 'Yaz Pikniği 2025',
name: 'Yaz Pikniği 2025',
description:
'Şirket çalışanları olarak doğayla iç içe harika bir gün geçirdik. Takım oyunları, barbekü ve çok eğlence!',
type: 'social',
categoryName: 'Spor',
typeName: 'Futbol Turnuvası',
date: new Date('2025-10-20'),
location: 'Polonezköy Piknik Alanı',
place: 'Polonezköy Piknik Alanı',
organizer: mockEmployees[4],
participants: 45,
photos: [
@ -860,11 +861,12 @@ export const mockEvents: CalendarEvent[] = [
},
{
id: 'evt2',
title: 'Hackathon 2025',
name: 'Hackathon 2025',
description: '24 saatlik yazılım geliştirme maratonu. İnovasyon, teknoloji ve takım çalışması!',
type: 'training',
categoryName: 'Spor',
typeName: 'training',
date: new Date('2025-20-22'),
location: 'Ofis - Ana Salon',
place: 'Ofis - Ana Salon',
organizer: mockEmployees[0],
participants: 28,
photos: [
@ -893,11 +895,12 @@ export const mockEvents: CalendarEvent[] = [
},
{
id: 'evt3',
title: 'Kurumsal Futbol Turnuvası',
name: 'Kurumsal Futbol Turnuvası',
description: 'Departmanlar arası futbol turnuvasında ter döktük, gol attık ve kazandık! 🏆',
type: 'sport',
categoryName: 'Spor',
typeName: 'sport',
date: new Date('2025-10-25'),
location: 'Spor Kompleksi Halı Saha',
place: 'Spor Kompleksi Halı Saha',
organizer: mockEmployees[2],
participants: 32,
photos: [
@ -920,11 +923,12 @@ export const mockEvents: CalendarEvent[] = [
},
{
id: 'evt4',
title: 'Yılbaşı Gala Gecesi 2024',
name: 'Yılbaşı Gala Gecesi 2024',
description: 'Harika bir yıla muhteşem bir gala ile veda ettik. Müzik, dans ve sürprizler!',
type: 'company',
categoryName: 'Spor',
typeName: 'company',
date: new Date('2024-12-28'),
location: 'Grand Hotel - Balo Salonu',
place: 'Grand Hotel - Balo Salonu',
organizer: mockEmployees[3],
participants: 68,
photos: [
@ -962,11 +966,12 @@ export const mockEvents: CalendarEvent[] = [
},
{
id: 'evt5',
title: 'Sanat Atölyesi - Ebru Workshop',
name: 'Sanat Atölyesi - Ebru Workshop',
description: 'Geleneksel Türk sanatı ebru yapımı atölyesinde harika eserler ortaya çıktı!',
type: 'culture',
categoryName: 'Spor',
typeName: 'culture',
date: new Date('2025-05-12'),
location: 'Ofis - Yaratıcı Alan',
place: 'Ofis - Yaratıcı Alan',
organizer: mockEmployees[1],
participants: 18,
photos: [

View file

@ -0,0 +1,31 @@
import { HrEmployee } from '@/types/hr'
export interface IntranetDashboardDto {
events: EventDto[];
}
// Etkinlik
export interface EventDto {
id: string
categoryName: string
typeName: string
date: Date
name: string
description: string
place: string
organizer: HrEmployee
participants: number
photos: string[]
comments: EventCommentDto[]
likes: number
isPublished: boolean
}
// Etkinlik Yorumu
export interface EventCommentDto {
id: string
author: HrEmployee
content: string
creationTime: Date
likes: number
}

View file

@ -20,12 +20,4 @@ export class AiService {
)
}
export const getAi = async (skipCount = 0, maxResultCount = 1000, sorting = 'botName') => {
const service = new AiService()
return await service.getList({
sorting,
skipCount,
maxResultCount,
})
}
export const aiService = new AiService()

View file

@ -0,0 +1,17 @@
import apiService, { Config } from './api.service'
import { IntranetDashboardDto } from '@/proxy/intranet/models'
export class IntranetService {
apiName = 'Default'
getDashboard = (config?: Partial<Config>) =>
apiService.fetchData<IntranetDashboardDto>(
{
method: 'GET',
url: '/api/app/intranet/intranet-dashboard',
},
{ apiName: this.apiName, ...config },
)
}
export const intranetService = new IntranetService()

View file

@ -17,31 +17,6 @@ export interface Announcement {
imageUrl?: string
}
// Etkinlik
export interface CalendarEvent {
id: string
title: string
description: string
type: 'social' | 'training' | 'company' | 'sport' | 'culture'
date: Date
location: string
organizer: HrEmployee
participants: number
photos: string[]
comments: EventComment[]
likes: number
isPublished: boolean
}
// Etkinlik Yorumu
export interface EventComment {
id: string
author: HrEmployee
content: string
creationTime: Date
likes: number
}
// Harcama
export interface ExpenseRequest {
id: string

View file

@ -1,10 +1,10 @@
import React, { useState, useRef, useEffect, SyntheticEvent } from 'react'
import { FaRobot } from 'react-icons/fa';
import { FaRobot } from 'react-icons/fa'
import { useStoreActions, useStoreState } from '@/store'
import { Avatar, Dropdown } from '@/components/ui'
import LoadAiPostsFromLocalStorage from './LoadAiPostsFromLocalStorage'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { getAi } from '@/services/ai.service'
import { aiService } from '@/services/ai.service'
import { AiDto } from '@/proxy/ai/models'
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
@ -60,7 +60,11 @@ const Assistant = () => {
useEffect(() => {
const fetchBots = async () => {
try {
const result = await getAi()
const result = await aiService.getList({
skipCount: 0,
maxResultCount: 1000,
sorting: 'botName',
})
const items =
result?.data?.items?.map((bot: AiDto) => ({
key: bot.id!,

View file

@ -34,18 +34,13 @@ import SocialWall from './SocialWall'
import { Announcement, Survey, SurveyAnswer } from '@/types/intranet'
import { Container } from '@/components/shared'
import { usePermission } from '@/utils/hooks/usePermission'
import { IntranetDashboardDto } from '@/proxy/intranet/models'
import { intranetService, IntranetService } from '@/services/intranet.service'
dayjs.locale('tr')
dayjs.extend(relativeTime)
dayjs.extend(isBetween)
interface WidgetConfig {
id: string
permission: string
component: React.ReactNode
column: 'left' | 'center' | 'right'
}
const WIDGET_ORDER_KEY = 'dashboard-widget-order'
const IntranetDashboard: React.FC = () => {
@ -63,6 +58,18 @@ const IntranetDashboard: React.FC = () => {
center: [],
right: [],
})
const [intranetDashboard, setIntranetDashboard] = useState<IntranetDashboardDto>()
const fetchIntranetDashboard = async () => {
const dashboard = await intranetService.getDashboard()
setIntranetDashboard(dashboard.data)
}
useEffect(() => {
fetchIntranetDashboard()
}, [])
// Drag state'leri birleştirildi
const [dragState, setDragState] = useState<{
draggedId: string | null
@ -173,11 +180,6 @@ const IntranetDashboard: React.FC = () => {
e.dataTransfer.setData('sourceColumn', column)
}
const handleDragOver = (e: React.DragEvent) => {
e.preventDefault()
e.dataTransfer.dropEffect = 'move'
}
const handleDragEnterWidget = (e: React.DragEvent, column: string, index: number) => {
// Sadece widget'ın üst kısmına yakınsa indicator göster
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()
@ -243,7 +245,7 @@ const IntranetDashboard: React.FC = () => {
const renderWidgetComponent = (widgetId: string) => {
switch (widgetId) {
case 'upcoming-events':
return <UpcomingEvents />
return <UpcomingEvents events={intranetDashboard?.events || []} />
case 'today-birthdays':
return <TodayBirthdays />
case 'recent-documents':

View file

@ -1,47 +0,0 @@
import React from 'react'
import { FaCalendarAlt } from 'react-icons/fa'
import dayjs from 'dayjs'
import { mockEvents } from '../../../mocks/mockIntranet'
const TodayEvents: React.FC = () => {
const todayEvents = mockEvents.filter(
(event) => event.isPublished && dayjs(event.date).isSame(dayjs(), 'day'),
)
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
<FaCalendarAlt className="w-5 h-5" />
Bugün
</h2>
</div>
<div className="p-4 space-y-3">
{todayEvents.length > 0 ? (
todayEvents.map((event) => (
<div
key={event.id}
className="p-3 rounded-lg border-l-4 bg-gray-50 dark:bg-gray-700/50 border-l-blue-500"
>
<h4 className="text-sm font-medium text-gray-900 dark:text-white">
{event.title}
</h4>
<p className="text-xs text-gray-600 dark:text-gray-400 mt-1">
{dayjs(event.date).format('DD MMMM YYYY')} - {event.location}
</p>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
{event.participants} katılımcı
</p>
</div>
))
) : (
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
Bugün etkinlik yok
</p>
)}
</div>
</div>
)
}
export default TodayEvents

View file

@ -1,10 +1,10 @@
import React from 'react'
import { FaCalendarAlt } from 'react-icons/fa'
import dayjs from 'dayjs'
import { mockEvents } from '../../../mocks/mockIntranet'
import { EventDto } from '@/proxy/intranet/models'
const UpcomingEvents: React.FC = () => {
const upcomingEvents = mockEvents.filter(
const UpcomingEvents: React.FC<{ events: EventDto[] }> = ({ events }) => {
const upcomingEvents = events.filter(
(event) =>
event.isPublished &&
dayjs(event.date).isAfter(dayjs()) &&
@ -26,11 +26,9 @@ const UpcomingEvents: React.FC = () => {
key={event.id}
className="p-3 rounded-lg border-l-4 bg-gray-50 dark:bg-gray-700/50 border-l-green-500"
>
<h4 className="text-sm font-medium text-gray-900 dark:text-white">
{event.title}
</h4>
<h4 className="text-sm font-medium text-gray-900 dark:text-white">{event.name}</h4>
<p className="text-xs text-gray-600 dark:text-gray-400 mt-1">
{dayjs(event.date).format('DD MMMM YYYY')} - {event.location}
{dayjs(event.date).format('DD MMMM YYYY')} - {event.place}
</p>
</div>
))