mockIntranet kaldırıldı
Intranet Dashboard düzeltildi.
This commit is contained in:
parent
264f802265
commit
988a8d0bfb
22 changed files with 422 additions and 3646 deletions
|
|
@ -17,5 +17,7 @@ public class IntranetDashboardDto
|
|||
public List<MealDto> Meals { get; set; } = [];
|
||||
public List<LeaveDto> Leaves { get; set; } = [];
|
||||
public List<OvertimeDto> Overtimes { get; set; } = [];
|
||||
public List<SurveyDto> Surveys { get; set; } = [];
|
||||
public List<SocialPostDto> SocialPosts { get; set; } = [];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Kurs.Platform.Intranet;
|
||||
|
||||
public class SocialPostDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid? EmployeeId { get; set; }
|
||||
public EmployeeDto? Employee { get; set; }
|
||||
public string Content { get; set; }
|
||||
|
||||
public int LikeCount { get; set; }
|
||||
public bool IsLiked { get; set; }
|
||||
public bool IsOwnPost { get; set; }
|
||||
|
||||
public SocialLocationDto? Location { get; set; }
|
||||
public SocialMediaDto? Media { get; set; }
|
||||
public List<SocialCommentDto> Comments { get; set; }
|
||||
public List<SocialLikeDto> Likes { get; set; }
|
||||
}
|
||||
|
||||
public class SocialLocationDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SocialPostId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public double? Lat { get; set; }
|
||||
public double? Lng { get; set; }
|
||||
public string? PlaceId { get; set; }
|
||||
}
|
||||
|
||||
public class SocialMediaDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SocialPostId { get; set; }
|
||||
public string Type { get; set; } // image | video | poll
|
||||
public string[] Urls { get; set; }
|
||||
|
||||
// Poll Fields
|
||||
public string? PollQuestion { get; set; }
|
||||
public int? PollTotalVotes { get; set; }
|
||||
public DateTime? PollEndsAt { get; set; }
|
||||
public string? PollUserVoteId { get; set; }
|
||||
|
||||
public List<SocialPollOptionDto> PollOptions { get; set; }
|
||||
}
|
||||
|
||||
public class SocialPollOptionDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SocialMediaId { get; set; }
|
||||
public string Text { get; set; }
|
||||
public int Votes { get; set; }
|
||||
}
|
||||
|
||||
public class SocialCommentDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SocialPostId { get; set; }
|
||||
public Guid? EmployeeId { get; set; }
|
||||
public EmployeeDto? Employee { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
public class SocialLikeDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SocialPostId { get; set; }
|
||||
public Guid? EmployeeId { get; set; }
|
||||
public EmployeeDto? Employee { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Kurs.Platform.Intranet;
|
||||
|
||||
public class SurveyDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public DateTime Deadline { get; set; }
|
||||
public int Responses { get; set; }
|
||||
public string Status { get; set; } // draft | active | closed
|
||||
public bool IsAnonymous { get; set; }
|
||||
|
||||
public List<SurveyQuestionDto> Questions { get; set; }
|
||||
}
|
||||
|
||||
public class SurveyQuestionDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SurveyId { get; set; }
|
||||
public string QuestionText { get; set; }
|
||||
public string Type { get; set; } // rating | multiple-choice | text | textarea | yes-no
|
||||
public int Order { get; set; }
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
public List<SurveyQuestionOptionDto> Options { get; set; }
|
||||
}
|
||||
|
||||
public class SurveyQuestionOptionDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid QuestionId { get; set; }
|
||||
public string Text { get; set; }
|
||||
public int Order { get; set; }
|
||||
}
|
||||
|
||||
public class SurveyResponseDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid SurveyId { get; set; }
|
||||
public Guid? EmployeeId { get; set; }
|
||||
public DateTime SubmissionTime { get; set; }
|
||||
|
||||
public List<SurveyAnswerDto> Answers { get; set; }
|
||||
}
|
||||
|
||||
public class SurveyAnswerDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid ResponseId { get; set; }
|
||||
public Guid QuestionId { get; set; }
|
||||
public string QuestionType { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ using Kurs.Platform.Entities;
|
|||
using Kurs.Platform.FileManagement;
|
||||
using Kurs.Platform.Intranet;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
|
|
@ -35,6 +36,8 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
|
|||
private readonly IRepository<Meal, Guid> _mealRepository;
|
||||
private readonly IRepository<Leave, Guid> _leaveRepository;
|
||||
private readonly IRepository<Overtime, Guid> _overtimeRepository;
|
||||
private readonly IRepository<Survey, Guid> _surveyRepository;
|
||||
private readonly IRepository<SocialPost, Guid> _socialPostRepository;
|
||||
|
||||
public IntranetAppService(
|
||||
ICurrentTenant currentTenant,
|
||||
|
|
@ -52,7 +55,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
|
|||
IRepository<ShuttleRoute, Guid> shuttleRouteRepository,
|
||||
IRepository<Meal, Guid> mealRepository,
|
||||
IRepository<Leave, Guid> leaveRepository,
|
||||
IRepository<Overtime, Guid> overtimeRepository
|
||||
IRepository<Overtime, Guid> overtimeRepository,
|
||||
IRepository<Survey, Guid> surveyRepository,
|
||||
IRepository<SocialPost, Guid> socialPostRepository
|
||||
)
|
||||
{
|
||||
_currentTenant = currentTenant;
|
||||
|
|
@ -71,6 +76,8 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
|
|||
_mealRepository = mealRepository;
|
||||
_leaveRepository = leaveRepository;
|
||||
_overtimeRepository = overtimeRepository;
|
||||
_surveyRepository = surveyRepository;
|
||||
_socialPostRepository = socialPostRepository;
|
||||
}
|
||||
|
||||
public async Task<IntranetDashboardDto> GetIntranetDashboardAsync()
|
||||
|
|
@ -88,10 +95,34 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
|
|||
ShuttleRoutes = await GetShuttleRoutesAsync(),
|
||||
Meals = await GetMealsAsync(),
|
||||
Leaves = await GetLeavesAsync(),
|
||||
Overtimes = await GetOvertimesAsync()
|
||||
Overtimes = await GetOvertimesAsync(),
|
||||
Surveys = await GetSurveysAsync(),
|
||||
SocialPosts = await GetSocialPostsAsync()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<List<SocialPostDto>> GetSocialPostsAsync()
|
||||
{
|
||||
var socialPosts = await _socialPostRepository
|
||||
.WithDetailsAsync(e => e.Employee, e => e.Location, e => e.Media, e => e.Comments, e => e.Likes)
|
||||
.ContinueWith(t => t.Result.ToList());
|
||||
|
||||
return ObjectMapper.Map<List<SocialPost>, List<SocialPostDto>>(socialPosts);
|
||||
}
|
||||
|
||||
private async Task<List<SurveyDto>> GetSurveysAsync()
|
||||
{
|
||||
var queryable = await _surveyRepository.GetQueryableAsync();
|
||||
|
||||
var surveys = queryable
|
||||
.Where(s => s.Status == "active")
|
||||
.Include(s => s.Questions)
|
||||
.ThenInclude(q => q.Options)
|
||||
.ToList();
|
||||
|
||||
return ObjectMapper.Map<List<Survey>, List<SurveyDto>>(surveys);
|
||||
}
|
||||
|
||||
private async Task<List<OvertimeDto>> GetOvertimesAsync()
|
||||
{
|
||||
var today = DateTime.Now;
|
||||
|
|
|
|||
|
|
@ -28,5 +28,17 @@ public class IntranetAutoMapperProfile : Profile
|
|||
CreateMap<ShuttleRoute, ShuttleRouteDto>()
|
||||
.ForMember(dest => dest.Route, opt => opt.Ignore());
|
||||
|
||||
CreateMap<Survey, SurveyDto>();
|
||||
CreateMap<SurveyQuestion, SurveyQuestionDto>();
|
||||
CreateMap<SurveyQuestionOption, SurveyQuestionOptionDto>();
|
||||
CreateMap<SurveyResponse, SurveyResponseDto>();
|
||||
CreateMap<SurveyAnswer, SurveyAnswerDto>();
|
||||
|
||||
CreateMap<SocialPost, SocialPostDto>();
|
||||
CreateMap<SocialLocation, SocialLocationDto>();
|
||||
CreateMap<SocialMedia, SocialMediaDto>();
|
||||
CreateMap<SocialPollOption, SocialPollOptionDto>();
|
||||
CreateMap<SocialComment, SocialCommentDto>();
|
||||
CreateMap<SocialLike, SocialLikeDto>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public class SocialPost : FullAuditedEntity<Guid>, IMultiTenant
|
|||
public Guid? TenantId { get; set; }
|
||||
|
||||
public Guid? EmployeeId { get; set; }
|
||||
public Employee? Employee { get; set; }
|
||||
public Employee Employee { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
|
|
@ -19,8 +19,8 @@ public class SocialPost : FullAuditedEntity<Guid>, IMultiTenant
|
|||
public bool IsOwnPost { get; set; }
|
||||
|
||||
// Relations
|
||||
public SocialLocation? Location { get; set; }
|
||||
public SocialMedia? Media { get; set; }
|
||||
public SocialLocation Location { get; set; }
|
||||
public SocialMedia Media { get; set; }
|
||||
public ICollection<SocialComment> Comments { get; set; }
|
||||
public ICollection<SocialLike> Likes { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
|||
namespace Kurs.Platform.Migrations
|
||||
{
|
||||
[DbContext(typeof(PlatformDbContext))]
|
||||
[Migration("20251029074530_Initial")]
|
||||
[Migration("20251029185945_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -28,7 +28,8 @@ export interface IntranetDashboardDto {
|
|||
meals: MealDto[]
|
||||
leaves: LeaveDto[]
|
||||
overtimes: OvertimeDto[]
|
||||
// surveys: Survey[]
|
||||
surveys: SurveyDto[]
|
||||
socialPosts: SocialPostDto[]
|
||||
// priorityTasks: TaskDto[]
|
||||
}
|
||||
|
||||
|
|
@ -323,3 +324,97 @@ export interface LeaveDto {
|
|||
creationTime: Date
|
||||
lastModificationTime: Date
|
||||
}
|
||||
|
||||
// Anket Cevap
|
||||
export interface SurveyAnswerDto {
|
||||
questionId: string
|
||||
questionType: 'rating' | 'multiple-choice' | 'text' | 'textarea' | 'yes-no'
|
||||
value: string | number | string[]
|
||||
}
|
||||
|
||||
// Sosyal Duvar - Comment Interface
|
||||
export interface SocialCommentDto {
|
||||
id: string
|
||||
creator: EmployeeDto
|
||||
content: string
|
||||
creationTime: Date
|
||||
}
|
||||
|
||||
export interface SocialPollOptionDto {
|
||||
id: string
|
||||
text: string
|
||||
votes: number
|
||||
}
|
||||
|
||||
// Sosyal Duvar - Social Media Interface
|
||||
export interface SocialMediaDto {
|
||||
id?: string
|
||||
type: 'image' | 'video' | 'poll'
|
||||
|
||||
// Ortak alanlar
|
||||
urls?: string[]
|
||||
|
||||
// Anket (poll) ile ilgili alanlar doğrudan burada
|
||||
pollQuestion?: string
|
||||
pollOptions?: SocialPollOptionDto[]
|
||||
pollTotalVotes?: number
|
||||
pollEndsAt?: Date
|
||||
pollUserVoteId?: string
|
||||
}
|
||||
|
||||
// Sosyal Duvar - Ana Interface
|
||||
export interface SocialPostDto {
|
||||
id: string
|
||||
employee: EmployeeDto
|
||||
content: string
|
||||
locationJson?: string
|
||||
media?: SocialMediaDto
|
||||
likeCount: number
|
||||
isLiked: boolean
|
||||
likeUsers: EmployeeDto[]
|
||||
comments: SocialCommentDto[]
|
||||
isOwnPost: boolean
|
||||
creationTime: Date
|
||||
}
|
||||
|
||||
// Anket Cevabı
|
||||
export interface SurveyResponseDto {
|
||||
id: string
|
||||
surveyId: string
|
||||
respondentId?: string // Anonymous ise null
|
||||
submissionTime: Date
|
||||
answers: SurveyAnswerDto[]
|
||||
}
|
||||
|
||||
// Anket Sorusu Seçeneği
|
||||
export interface SurveyQuestionOptionDto {
|
||||
id: string
|
||||
text: string
|
||||
order: number
|
||||
}
|
||||
|
||||
// Anket Sorusu
|
||||
export interface SurveyQuestionDto {
|
||||
id: string
|
||||
surveyId: string
|
||||
questionText: string
|
||||
type: 'rating' | 'multiple-choice' | 'text' | 'textarea' | 'yes-no'
|
||||
order: number
|
||||
isRequired: boolean
|
||||
options?: SurveyQuestionOptionDto[]
|
||||
}
|
||||
|
||||
// Anket
|
||||
export interface SurveyDto {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
creatorId: EmployeeDto
|
||||
creationTime: Date
|
||||
deadline: Date
|
||||
questions: SurveyQuestionDto[]
|
||||
responses: number
|
||||
targetAudience: string[]
|
||||
status: 'draft' | 'active' | 'closed'
|
||||
isAnonymous: boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import { EmployeeDto } from "@/proxy/intranet/models"
|
||||
import {
|
||||
EmployeeDto,
|
||||
SurveyQuestionDto,
|
||||
} from '@/proxy/intranet/models'
|
||||
|
||||
// Görev
|
||||
export interface Task {
|
||||
|
|
@ -16,102 +19,3 @@ export interface Task {
|
|||
attachments?: { name: string; url: string }[]
|
||||
comments: number
|
||||
}
|
||||
|
||||
// Anket
|
||||
export interface Survey {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
creatorId: EmployeeDto
|
||||
creationTime: Date
|
||||
deadline: Date
|
||||
questions: SurveyQuestion[]
|
||||
responses: number
|
||||
targetAudience: string[]
|
||||
status: 'draft' | 'active' | 'closed'
|
||||
isAnonymous: boolean
|
||||
}
|
||||
|
||||
// Anket Sorusu
|
||||
export interface SurveyQuestion {
|
||||
id: string
|
||||
surveyId: string
|
||||
questionText: string
|
||||
type: 'rating' | 'multiple-choice' | 'text' | 'textarea' | 'yes-no'
|
||||
order: number
|
||||
isRequired: boolean
|
||||
options?: SurveyQuestionOption[]
|
||||
ratingConfig?: {
|
||||
min: number
|
||||
max: number
|
||||
labels?: { [key: number]: string }
|
||||
}
|
||||
}
|
||||
|
||||
// Anket Sorusu Seçeneği
|
||||
export interface SurveyQuestionOption {
|
||||
id: string
|
||||
text: string
|
||||
order: number
|
||||
}
|
||||
|
||||
// Anket Cevabı
|
||||
export interface SurveyResponse {
|
||||
id: string
|
||||
surveyId: string
|
||||
respondentId?: string // Anonymous ise null
|
||||
submissionTime: Date
|
||||
answers: SurveyAnswer[]
|
||||
}
|
||||
|
||||
// Anket Cevap
|
||||
export interface SurveyAnswer {
|
||||
questionId: string
|
||||
questionType: 'rating' | 'multiple-choice' | 'text' | 'textarea' | 'yes-no'
|
||||
value: string | number | string[]
|
||||
}
|
||||
|
||||
// Sosyal Duvar - Ana Interface
|
||||
export interface SocialPost {
|
||||
id: string
|
||||
creator: EmployeeDto
|
||||
content: string
|
||||
locationJson?: string
|
||||
media?: SocialMedia
|
||||
likeCount: number
|
||||
isLiked: boolean
|
||||
likeUsers: EmployeeDto[]
|
||||
comments: SocialComment[]
|
||||
isOwnPost: boolean
|
||||
creationTime: Date
|
||||
}
|
||||
|
||||
// Sosyal Duvar - Social Media Interface
|
||||
export interface SocialMedia {
|
||||
id?: string
|
||||
type: 'image' | 'video' | 'poll'
|
||||
|
||||
// Ortak alanlar
|
||||
urls?: string[]
|
||||
|
||||
// Anket (poll) ile ilgili alanlar doğrudan burada
|
||||
pollQuestion?: string
|
||||
pollOptions?: SocialPollOption[]
|
||||
pollTotalVotes?: number
|
||||
pollEndsAt?: Date
|
||||
pollUserVoteId?: string
|
||||
}
|
||||
|
||||
export interface SocialPollOption {
|
||||
id: string
|
||||
text: string
|
||||
votes: number
|
||||
}
|
||||
|
||||
// Sosyal Duvar - Comment Interface
|
||||
export interface SocialComment {
|
||||
id: string
|
||||
creator: EmployeeDto
|
||||
content: string
|
||||
creationTime: Date
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -15,11 +15,12 @@ import {
|
|||
FaMapMarkerAlt,
|
||||
FaBriefcase,
|
||||
} from 'react-icons/fa'
|
||||
import { EmployeeDto, HrOrganizationChart as OrgChart } from '../../../types/hr'
|
||||
import { HrOrganizationChart as OrgChart } from '../../../types/hr'
|
||||
import { mockEmployees } from '../../../mocks/mockEmployees'
|
||||
import { mockDepartments } from '../../../mocks/mockDepartments'
|
||||
import Widget from '../../../components/common/Widget'
|
||||
import { Container } from '@/components/shared'
|
||||
import { EmployeeDto } from '@/proxy/intranet/models'
|
||||
|
||||
// Dinamik organizasyon verisi oluşturma fonksiyonu
|
||||
const generateOrganizationData = (): OrgChart[] => {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -29,10 +29,10 @@ import AnnouncementDetailModal from './modals/AnnouncementDetailModal'
|
|||
|
||||
// Social Wall
|
||||
import SocialWall from './SocialWall'
|
||||
import { Survey, SurveyAnswer } from '@/types/intranet'
|
||||
import { SurveyDto } from '@/types/intranet'
|
||||
import { Container } from '@/components/shared'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
import { AnnouncementDto, IntranetDashboardDto } from '@/proxy/intranet/models'
|
||||
import { AnnouncementDto, IntranetDashboardDto, SurveyAnswerDto } from '@/proxy/intranet/models'
|
||||
import { intranetService } from '@/services/intranet.service'
|
||||
import Announcements from './widgets/Announcements'
|
||||
import ShuttleRoute from './widgets/ShuttleRoute'
|
||||
|
|
@ -46,7 +46,7 @@ const WIDGET_ORDER_KEY = 'dashboard-widget-order'
|
|||
const IntranetDashboard: React.FC = () => {
|
||||
const { checkPermission } = usePermission()
|
||||
const [selectedAnnouncement, setSelectedAnnouncement] = useState<AnnouncementDto | null>(null)
|
||||
const [selectedSurvey, setSelectedSurvey] = useState<Survey | null>(null)
|
||||
const [selectedSurvey, setSelectedSurvey] = useState<SurveyDto | null>(null)
|
||||
const [showSurveyModal, setShowSurveyModal] = useState(false)
|
||||
const [showLeaveModal, setShowLeaveModal] = useState(false)
|
||||
const [showOvertimeModal, setShowOvertimeModal] = useState(false)
|
||||
|
|
@ -81,12 +81,12 @@ const IntranetDashboard: React.FC = () => {
|
|||
targetIndex: null,
|
||||
})
|
||||
|
||||
const handleTakeSurvey = (survey: Survey) => {
|
||||
const handleTakeSurvey = (survey: SurveyDto) => {
|
||||
setSelectedSurvey(survey)
|
||||
setShowSurveyModal(true)
|
||||
}
|
||||
|
||||
const handleSubmitSurvey = (answers: SurveyAnswer[]) => {
|
||||
const handleSubmitSurvey = (answers: SurveyAnswerDto[]) => {
|
||||
setShowSurveyModal(false)
|
||||
setSelectedSurvey(null)
|
||||
}
|
||||
|
|
@ -299,11 +299,15 @@ const IntranetDashboard: React.FC = () => {
|
|||
onNewOvertime={() => setShowOvertimeModal(true)}
|
||||
/>
|
||||
)
|
||||
|
||||
case 'active-surveys':
|
||||
return <ActiveSurveys onTakeSurvey={handleTakeSurvey} />
|
||||
return (
|
||||
<ActiveSurveys
|
||||
surveys={intranetDashboard?.surveys || []}
|
||||
onTakeSurvey={handleTakeSurvey}
|
||||
/>
|
||||
)
|
||||
case 'social-wall':
|
||||
return <SocialWall />
|
||||
return <SocialWall posts={intranetDashboard?.socialPosts || []} />
|
||||
case 'priority-tasks':
|
||||
return <PriorityTasks />
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from 'react-icons/fa'
|
||||
import MediaManager from './MediaManager'
|
||||
import LocationPicker from './LocationPicker'
|
||||
import { SocialMedia } from '@/types/intranet'
|
||||
import { SocialMediaDto } from '@/proxy/intranet/models'
|
||||
|
||||
interface CreatePostProps {
|
||||
onCreatePost: (post: {
|
||||
|
|
@ -19,7 +19,7 @@ interface CreatePostProps {
|
|||
location?: string
|
||||
media?: {
|
||||
type: 'mixed' | 'poll'
|
||||
mediaItems?: SocialMedia[]
|
||||
mediaItems?: SocialMediaDto[]
|
||||
poll?: {
|
||||
question: string
|
||||
options: Array<{ text: string }>
|
||||
|
|
@ -31,7 +31,7 @@ interface CreatePostProps {
|
|||
const CreatePost: React.FC<CreatePostProps> = ({ onCreatePost }) => {
|
||||
const [content, setContent] = useState('')
|
||||
const [mediaType, setMediaType] = useState<'media' | 'poll' | null>(null)
|
||||
const [mediaItems, setMediaItems] = useState<SocialMedia[]>([])
|
||||
const [mediaItems, setMediaItems] = useState<SocialMediaDto[]>([])
|
||||
const [location, setLocation] = useState<string | null>(null)
|
||||
const [pollQuestion, setPollQuestion] = useState('')
|
||||
const [pollOptions, setPollOptions] = useState(['', ''])
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ import Video from 'yet-another-react-lightbox/plugins/video'
|
|||
import Zoom from 'yet-another-react-lightbox/plugins/zoom'
|
||||
import Counter from 'yet-another-react-lightbox/plugins/counter'
|
||||
import 'yet-another-react-lightbox/plugins/counter.css'
|
||||
import { SocialMedia } from '@/types/intranet'
|
||||
import { SocialMediaDto } from '@/proxy/intranet/models'
|
||||
|
||||
interface MediaLightboxProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
media: SocialMedia
|
||||
media: SocialMediaDto
|
||||
startIndex?: number
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import React, { useState } from 'react'
|
|||
import { motion } from 'framer-motion'
|
||||
import { FaTimes, FaLink, FaUpload } from 'react-icons/fa'
|
||||
import classNames from 'classnames'
|
||||
import { SocialMedia } from '@/types/intranet'
|
||||
import { SocialMediaDto } from '@/proxy/intranet/models'
|
||||
|
||||
interface MediaManagerProps {
|
||||
media: SocialMedia[]
|
||||
onChange: (media: SocialMedia[]) => void
|
||||
media: SocialMediaDto[]
|
||||
onChange: (media: SocialMediaDto[]) => void
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
|
|||
const files = e.target.files
|
||||
if (!files) return
|
||||
|
||||
const newMedia: SocialMedia[] = Array.from(files).map((file) => ({
|
||||
const newMedia: SocialMediaDto[] = Array.from(files).map((file) => ({
|
||||
id: Math.random().toString(36).substr(2, 9),
|
||||
type: file.type.startsWith('video/') ? 'video' : 'image',
|
||||
urls: [URL.createObjectURL(file)],
|
||||
|
|
@ -33,7 +33,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
|
|||
const handleUrlAdd = () => {
|
||||
if (!urlInput.trim()) return
|
||||
|
||||
const newMedia: SocialMedia = {
|
||||
const newMedia: SocialMediaDto = {
|
||||
id: Math.random().toString(36).substr(2, 9),
|
||||
type: mediaType,
|
||||
urls: [urlInput]
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ import {
|
|||
import MediaLightbox from './MediaLightbox'
|
||||
import LocationMap from './LocationMap'
|
||||
import UserProfileCard from './UserProfileCard'
|
||||
import { SocialPost } from '@/types/intranet'
|
||||
import { SocialPostDto } from '@/proxy/intranet/models'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.locale('tr')
|
||||
|
||||
interface PostItemProps {
|
||||
post: SocialPost
|
||||
post: SocialPostDto
|
||||
onLike: (postId: string) => void
|
||||
onComment: (postId: string, content: string) => void
|
||||
onDelete: (postId: string) => void
|
||||
|
|
@ -258,22 +258,22 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
|
|||
onMouseLeave={() => setShowUserCard(false)}
|
||||
>
|
||||
<img
|
||||
src={post.creator.avatar || 'https://i.pravatar.cc/150?img=1'}
|
||||
alt={post.creator.fullName}
|
||||
src={post.employee.avatar || 'https://i.pravatar.cc/150?img=1'}
|
||||
alt={post.employee.fullName}
|
||||
className="w-12 h-12 rounded-full object-cover cursor-pointer ring-2 ring-transparent hover:ring-blue-500 transition-all"
|
||||
/>
|
||||
<AnimatePresence>
|
||||
{showUserCard && (
|
||||
<UserProfileCard
|
||||
user={{
|
||||
id: post.creator.id,
|
||||
name: post.creator.fullName,
|
||||
avatar: post.creator.avatar || 'https://i.pravatar.cc/150?img=1',
|
||||
title: post.creator.jobPosition?.name || 'Çalışan',
|
||||
email: post.creator.email,
|
||||
phone: post.creator.phone,
|
||||
department: post.creator.department?.name,
|
||||
location: post.creator.workLocation
|
||||
id: post.employee.id,
|
||||
name: post.employee.fullName,
|
||||
avatar: post.employee.avatar || 'https://i.pravatar.cc/150?img=1',
|
||||
title: post.employee.jobPosition?.name || 'Çalışan',
|
||||
email: post.employee.email,
|
||||
phone: post.employee.phone,
|
||||
department: post.employee.department?.name,
|
||||
location: post.employee.workLocation
|
||||
}}
|
||||
position="bottom"
|
||||
/>
|
||||
|
|
@ -282,10 +282,10 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
|
|||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 dark:text-gray-100">
|
||||
{post.creator.fullName}
|
||||
{post.employee.fullName}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
{post.creator.jobPosition?.name || 'Çalışan'} • {dayjs(post.creationTime).fromNow()}
|
||||
{post.employee.jobPosition?.name || 'Çalışan'} • {dayjs(post.creationTime).fromNow()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import React, { useState } from 'react'
|
||||
import { AnimatePresence } from 'framer-motion'
|
||||
import PostItem from './PostItem'
|
||||
import { SocialMedia } from '@/types/intranet'
|
||||
import CreatePost from './CreatePost'
|
||||
import { SocialPost } from '@/types/intranet'
|
||||
import { EmployeeDto } from '@/types/hr'
|
||||
import { mockSocialPosts } from '@/mocks/mockIntranet'
|
||||
// import { mockSocialPosts } from '@/mocks/mockIntranet'
|
||||
import { mockEmployees } from '@/mocks/mockEmployees'
|
||||
import { EmployeeDto, SocialMediaDto, SocialPostDto } from '@/proxy/intranet/models'
|
||||
|
||||
const SocialWall: React.FC = () => {
|
||||
const [posts, setPosts] = useState<SocialPost[]>(mockSocialPosts)
|
||||
const SocialWall: React.FC<{ posts: SocialPostDto[] }> = ({ posts }) => {
|
||||
// const [posts, setPosts] = useState<SocialPost[]>(mockSocialPosts)
|
||||
const [filter, setFilter] = useState<'all' | 'mine'>('all')
|
||||
|
||||
// Ali Öztürk'ü "Siz" kullanıcısı olarak kullan
|
||||
|
|
@ -20,7 +18,7 @@ const SocialWall: React.FC = () => {
|
|||
location?: string
|
||||
media?: {
|
||||
type: 'mixed' | 'poll'
|
||||
mediaItems?: SocialMedia[]
|
||||
mediaItems?: SocialMediaDto[]
|
||||
poll?: {
|
||||
question: string
|
||||
options: Array<{ text: string }>
|
||||
|
|
@ -32,24 +30,24 @@ const SocialWall: React.FC = () => {
|
|||
if (postData.media) {
|
||||
if (postData.media.type === 'mixed' && postData.media.mediaItems) {
|
||||
// Convert MediaItems to post format
|
||||
const images = postData.media.mediaItems.filter(m => m.type === 'image')
|
||||
const videos = postData.media.mediaItems.filter(m => m.type === 'video')
|
||||
|
||||
const images = postData.media.mediaItems.filter((m) => m.type === 'image')
|
||||
const videos = postData.media.mediaItems.filter((m) => m.type === 'video')
|
||||
|
||||
if (images.length > 0 && videos.length === 0) {
|
||||
mediaForPost = {
|
||||
type: 'image' as const,
|
||||
urls: images.map(i => i.urls?.[0]).filter(url => url !== undefined) as string[]
|
||||
urls: images.map((i) => i.urls?.[0]).filter((url) => url !== undefined) as string[],
|
||||
}
|
||||
} else if (videos.length > 0 && images.length === 0) {
|
||||
mediaForPost = {
|
||||
type: 'video' as const,
|
||||
urls: videos[0].urls || []
|
||||
urls: videos[0].urls || [],
|
||||
}
|
||||
} else if (images.length > 0 || videos.length > 0) {
|
||||
// Mixed media - use first image for now
|
||||
mediaForPost = {
|
||||
type: 'image' as const,
|
||||
urls: images.map(i => i.urls?.[0]).filter(url => url !== undefined) as string[]
|
||||
urls: images.map((i) => i.urls?.[0]).filter((url) => url !== undefined) as string[],
|
||||
}
|
||||
}
|
||||
} else if (postData.media.type === 'poll' && postData.media.poll) {
|
||||
|
|
@ -59,17 +57,17 @@ const SocialWall: React.FC = () => {
|
|||
pollOptions: postData.media.poll.options.map((opt, index) => ({
|
||||
id: `opt-${index}`,
|
||||
text: opt.text,
|
||||
votes: 0
|
||||
votes: 0,
|
||||
})),
|
||||
pollTotalVotes: 0,
|
||||
pollEndsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
|
||||
pollEndsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newPost: SocialPost = {
|
||||
const newPost: SocialPostDto = {
|
||||
id: Date.now().toString(),
|
||||
creator: currentUserAuthor,
|
||||
employee: currentUserAuthor,
|
||||
content: postData.content,
|
||||
creationTime: new Date(),
|
||||
media: mediaForPost,
|
||||
|
|
@ -78,79 +76,77 @@ const SocialWall: React.FC = () => {
|
|||
isLiked: false,
|
||||
likeUsers: [],
|
||||
comments: [],
|
||||
isOwnPost: true
|
||||
isOwnPost: true,
|
||||
}
|
||||
|
||||
setPosts([newPost, ...posts])
|
||||
// setPosts([newPost, ...posts])
|
||||
}
|
||||
|
||||
const handleLike = (postId: string) => {
|
||||
setPosts(
|
||||
posts.map((post) => {
|
||||
if (post.id === postId) {
|
||||
return {
|
||||
...post,
|
||||
likeCount: post.isLiked ? post.likeCount - 1 : post.likeCount + 1,
|
||||
isLiked: !post.isLiked
|
||||
}
|
||||
}
|
||||
return post
|
||||
})
|
||||
)
|
||||
// setPosts(
|
||||
// posts.map((post) => {
|
||||
// if (post.id === postId) {
|
||||
// return {
|
||||
// ...post,
|
||||
// likeCount: post.isLiked ? post.likeCount - 1 : post.likeCount + 1,
|
||||
// isLiked: !post.isLiked
|
||||
// }
|
||||
// }
|
||||
// return post
|
||||
// })
|
||||
// )
|
||||
}
|
||||
|
||||
const handleComment = (postId: string, content: string) => {
|
||||
setPosts(
|
||||
posts.map((post) => {
|
||||
if (post.id === postId) {
|
||||
const commentAuthor = currentUserAuthor
|
||||
|
||||
const newComment = {
|
||||
id: Date.now().toString(),
|
||||
creator: commentAuthor,
|
||||
content,
|
||||
creationTime: new Date()
|
||||
}
|
||||
return {
|
||||
...post,
|
||||
comments: [...post.comments, newComment]
|
||||
}
|
||||
}
|
||||
return post
|
||||
})
|
||||
)
|
||||
// setPosts(
|
||||
// posts.map((post) => {
|
||||
// if (post.id === postId) {
|
||||
// const commentAuthor = currentUserAuthor
|
||||
// const newComment = {
|
||||
// id: Date.now().toString(),
|
||||
// creator: commentAuthor,
|
||||
// content,
|
||||
// creationTime: new Date()
|
||||
// }
|
||||
// return {
|
||||
// ...post,
|
||||
// comments: [...post.comments, newComment]
|
||||
// }
|
||||
// }
|
||||
// return post
|
||||
// })
|
||||
// )
|
||||
}
|
||||
|
||||
const handleDelete = (postId: string) => {
|
||||
if (window.confirm('Bu gönderiyi silmek istediğinizden emin misiniz?')) {
|
||||
setPosts(posts.filter((post) => post.id !== postId))
|
||||
// setPosts(posts.filter((post) => post.id !== postId))
|
||||
}
|
||||
}
|
||||
|
||||
const handleVote = (postId: string, optionId: string) => {
|
||||
setPosts(
|
||||
posts.map((post) => {
|
||||
if (post.id === postId && post.media?.type === 'poll' && post.media.pollOptions) {
|
||||
// If user already voted, don't allow voting again
|
||||
if (post.media.pollUserVoteId) {
|
||||
return post
|
||||
}
|
||||
|
||||
return {
|
||||
...post,
|
||||
media: {
|
||||
...post.media,
|
||||
pollOptions: post.media.pollOptions.map((opt) =>
|
||||
opt.id === optionId ? { ...opt, votes: opt.votes + 1 } : opt
|
||||
),
|
||||
pollTotalVotes: (post.media.pollTotalVotes || 0) + 1,
|
||||
pollUserVoteId: optionId
|
||||
}
|
||||
}
|
||||
}
|
||||
return post
|
||||
})
|
||||
)
|
||||
// setPosts(
|
||||
// posts.map((post) => {
|
||||
// if (post.id === postId && post.media?.type === 'poll' && post.media.pollOptions) {
|
||||
// // If user already voted, don't allow voting again
|
||||
// if (post.media.pollUserVoteId) {
|
||||
// return post
|
||||
// }
|
||||
// return {
|
||||
// ...post,
|
||||
// media: {
|
||||
// ...post.media,
|
||||
// pollOptions: post.media.pollOptions.map((opt) =>
|
||||
// opt.id === optionId ? { ...opt, votes: opt.votes + 1 } : opt
|
||||
// ),
|
||||
// pollTotalVotes: (post.media.pollTotalVotes || 0) + 1,
|
||||
// pollUserVoteId: optionId
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return post
|
||||
// })
|
||||
// )
|
||||
}
|
||||
|
||||
const filteredPosts = filter === 'mine' ? posts.filter((post) => post.isOwnPost) : posts
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useState } from 'react'
|
||||
import { motion } from 'framer-motion'
|
||||
import { FaTimes } from 'react-icons/fa'
|
||||
import { Survey, SurveyQuestion, SurveyAnswer } from '@/types/intranet'
|
||||
import { SurveyAnswerDto, SurveyDto, SurveyQuestionDto } from '@/proxy/intranet/models'
|
||||
|
||||
interface SurveyModalProps {
|
||||
survey: Survey
|
||||
survey: SurveyDto
|
||||
onClose: () => void
|
||||
onSubmit: (answers: SurveyAnswer[]) => void
|
||||
onSubmit: (answers: SurveyAnswerDto[]) => void
|
||||
}
|
||||
|
||||
const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit }) => {
|
||||
|
|
@ -14,51 +14,52 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
const [errors, setErrors] = useState<{ [questionId: string]: string }>({})
|
||||
|
||||
const handleAnswerChange = (questionId: string, value: any) => {
|
||||
setAnswers(prev => ({
|
||||
setAnswers((prev) => ({
|
||||
...prev,
|
||||
[questionId]: value
|
||||
[questionId]: value,
|
||||
}))
|
||||
|
||||
|
||||
// Clear error when user provides an answer
|
||||
if (errors[questionId]) {
|
||||
setErrors(prev => ({
|
||||
setErrors((prev) => ({
|
||||
...prev,
|
||||
[questionId]: ''
|
||||
[questionId]: '',
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
const validateAnswers = (): boolean => {
|
||||
const newErrors: { [questionId: string]: string } = {}
|
||||
|
||||
survey.questions.forEach(question => {
|
||||
|
||||
survey.questions.forEach((question) => {
|
||||
if (question.isRequired && (!answers[question.id] || answers[question.id] === '')) {
|
||||
newErrors[question.id] = 'Bu alan zorunludur'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
|
||||
if (!validateAnswers()) {
|
||||
return
|
||||
}
|
||||
|
||||
const surveyAnswers: SurveyAnswer[] = survey.questions.map(question => ({
|
||||
const surveyAnswers: SurveyAnswerDto[] = survey.questions.map((question) => ({
|
||||
questionId: question.id,
|
||||
questionType: question.type,
|
||||
value: answers[question.id] || (question.type === 'multiple-choice' ? '' :
|
||||
question.type === 'rating' ? 0 : '')
|
||||
value:
|
||||
answers[question.id] ||
|
||||
(question.type === 'multiple-choice' ? '' : question.type === 'rating' ? 0 : ''),
|
||||
}))
|
||||
|
||||
onSubmit(surveyAnswers)
|
||||
}
|
||||
|
||||
const renderQuestion = (question: SurveyQuestion, index: number) => {
|
||||
const renderQuestion = (question: SurveyQuestionDto, index: number) => {
|
||||
const questionNumber = index + 1
|
||||
const hasError = !!errors[question.id]
|
||||
|
||||
|
|
@ -69,34 +70,9 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{questionNumber}. {question.questionText} {question.isRequired && '*'}
|
||||
</label>
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{Array.from({ length: question.ratingConfig!.max - question.ratingConfig!.min + 1 }, (_, i) => {
|
||||
const value = question.ratingConfig!.min + i
|
||||
const label = question.ratingConfig!.labels?.[value] || value.toString()
|
||||
return (
|
||||
<label
|
||||
key={value}
|
||||
className={`flex flex-col items-center gap-1 px-3 py-2 border rounded-lg cursor-pointer transition-colors ${
|
||||
answers[question.id] === value
|
||||
? 'bg-blue-100 border-blue-500 dark:bg-blue-900/30 dark:border-blue-400'
|
||||
: 'border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700'
|
||||
}`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name={`question-${question.id}`}
|
||||
value={value}
|
||||
checked={answers[question.id] === value}
|
||||
onChange={(e) => handleAnswerChange(question.id, parseInt(e.target.value))}
|
||||
className="sr-only"
|
||||
/>
|
||||
<span className="font-medium text-gray-900 dark:text-white">{value}</span>
|
||||
<span className="text-xs text-gray-500 dark:text-gray-400 text-center">{label}</span>
|
||||
</label>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{hasError && <p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>}
|
||||
{hasError && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
|
@ -107,7 +83,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
{questionNumber}. {question.questionText} {question.isRequired && '*'}
|
||||
</label>
|
||||
<div className="space-y-2">
|
||||
{question.options?.map(option => (
|
||||
{question.options?.map((option) => (
|
||||
<label
|
||||
key={option.id}
|
||||
className={`flex items-center gap-3 p-3 border rounded-lg cursor-pointer transition-colors ${
|
||||
|
|
@ -128,7 +104,9 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
</label>
|
||||
))}
|
||||
</div>
|
||||
{hasError && <p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>}
|
||||
{hasError && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
|
@ -139,7 +117,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
{questionNumber}. {question.questionText} {question.isRequired && '*'}
|
||||
</label>
|
||||
<div className="flex gap-4">
|
||||
{['yes', 'no'].map(value => (
|
||||
{['yes', 'no'].map((value) => (
|
||||
<label
|
||||
key={value}
|
||||
className={`flex items-center gap-2 px-4 py-2 border rounded-lg cursor-pointer transition-colors ${
|
||||
|
|
@ -162,7 +140,9 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
</label>
|
||||
))}
|
||||
</div>
|
||||
{hasError && <p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>}
|
||||
{hasError && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
|
@ -181,7 +161,9 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
}`}
|
||||
placeholder="Cevabınızı yazın..."
|
||||
/>
|
||||
{hasError && <p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>}
|
||||
{hasError && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
|
@ -200,7 +182,9 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
}`}
|
||||
placeholder="Yorumlarınızı buraya yazabilirsiniz..."
|
||||
/>
|
||||
{hasError && <p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>}
|
||||
{hasError && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
|
@ -231,9 +215,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||
{survey.title}
|
||||
</h2>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
||||
{survey.description}
|
||||
</p>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">{survey.description}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
|
|
@ -253,8 +235,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
|
|||
{!survey.isAnonymous && (
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-3">
|
||||
<p className="text-sm text-blue-700 dark:text-blue-300">
|
||||
ℹ️ Bu anket isim belirtilerek doldurulmaktadır. Yanıtlarınız
|
||||
kaydedilecektir.
|
||||
ℹ️ Bu anket isim belirtilerek doldurulmaktadır. Yanıtlarınız kaydedilecektir.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
import React from 'react'
|
||||
import { FaClipboardCheck, FaQuestionCircle, FaUsers, FaClock, FaArrowRight } from 'react-icons/fa'
|
||||
import dayjs from 'dayjs'
|
||||
import { mockSurveys } from '../../../mocks/mockIntranet'
|
||||
import { Survey } from '@/types/intranet'
|
||||
import { SurveyDto } from '@/proxy/intranet/models'
|
||||
// import { mockSurveys } from '../../../mocks/mockIntranet'
|
||||
|
||||
interface ActiveSurveysProps {
|
||||
onTakeSurvey: (survey: Survey) => void
|
||||
surveys?: SurveyDto[]
|
||||
onTakeSurvey: (survey: SurveyDto) => void
|
||||
}
|
||||
|
||||
const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ onTakeSurvey }) => {
|
||||
const activeSurveys = mockSurveys.filter((s) => s.status === 'active').slice(0, 3)
|
||||
|
||||
const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey }) => {
|
||||
return (
|
||||
<div className="bg-gradient-to-br from-white to-gray-50 dark:from-gray-800 dark:to-gray-850 rounded-xl shadow-lg border border-gray-200/50 dark:border-gray-700/50 overflow-hidden">
|
||||
{/* Header with gradient */}
|
||||
|
|
@ -23,7 +22,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ onTakeSurvey }) => {
|
|||
</div>
|
||||
|
||||
<div className="p-6 space-y-4">
|
||||
{activeSurveys.map((survey, index) => {
|
||||
{surveys?.map((survey, index) => {
|
||||
const daysLeft = dayjs(survey.deadline).diff(dayjs(), 'day')
|
||||
const urgency = daysLeft <= 3 ? 'urgent' : daysLeft <= 7 ? 'warning' : 'normal'
|
||||
|
||||
|
|
@ -124,7 +123,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ onTakeSurvey }) => {
|
|||
)
|
||||
})}
|
||||
|
||||
{activeSurveys.length === 0 && (
|
||||
{surveys?.length === 0 && (
|
||||
<div className="text-center py-12">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gray-100 dark:bg-gray-700 rounded-full mb-4">
|
||||
<FaClipboardCheck className="w-8 h-8 text-gray-400" />
|
||||
|
|
|
|||
Loading…
Reference in a new issue