Initial version

This commit is contained in:
awe
2025-09-23 14:53:35 +03:00
parent b4aa400164
commit b61e3f93d4
27 changed files with 7528 additions and 0 deletions

41
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

36
frontend/README.md Normal file
View File

@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@ -0,0 +1,25 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{
ignores: [
"node_modules/**",
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
],
},
];
export default eslintConfig;

7
frontend/next.config.ts Normal file
View File

@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;

6090
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

27
frontend/package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack",
"start": "next start",
"lint": "eslint"
},
"dependencies": {
"react": "19.1.0",
"react-dom": "19.1.0",
"next": "15.5.3"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@tailwindcss/postcss": "^4",
"tailwindcss": "^4",
"eslint": "^9",
"eslint-config-next": "15.5.3",
"@eslint/eslintrc": "^3"
}
}

View File

@ -0,0 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
};
export default config;

1
frontend/public/file.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

1
frontend/public/next.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@ -0,0 +1,226 @@
'use client';
import { useState } from 'react';
export default function ContactsPage() {
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: ''
});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// В реальном приложении здесь была бы отправка формы
alert('Сообщение отправлено! (это демо-версия)');
setFormData({ name: '', email: '', subject: '', message: '' });
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-4">Контакты</h1>
<p className="text-lg text-gray-600">
Свяжитесь с нами для получения дополнительной информации о наших исследованиях и возможностях сотрудничества
</p>
</div>
<div className="grid lg:grid-cols-2 gap-12">
{/* Contact Information */}
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-6">Контактная информация</h2>
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold text-gray-900 mb-3">Адрес</h3>
<div className="flex items-start space-x-3">
<span className="text-blue-600 mt-1">📍</span>
<div>
<p className="text-gray-700">119991, Москва</p>
<p className="text-gray-700">ул. Научная, д. 1</p>
<p className="text-gray-700">Отдел радиофотоники</p>
</div>
</div>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 mb-3">Телефон</h3>
<div className="flex items-center space-x-3">
<span className="text-blue-600">📞</span>
<a href="tel:+74951234567" className="text-gray-700 hover:text-blue-600 transition-colors">
+7 (495) 123-45-67
</a>
</div>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 mb-3">Email</h3>
<div className="flex items-center space-x-3">
<span className="text-blue-600">📧</span>
<a href="mailto:info@radiophotonics.ru" className="text-gray-700 hover:text-blue-600 transition-colors">
info@radiophotonics.ru
</a>
</div>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 mb-3">Время работы</h3>
<div className="flex items-start space-x-3">
<span className="text-blue-600 mt-1">🕐</span>
<div>
<p className="text-gray-700">Понедельник - Пятница: 9:00 - 18:00</p>
<p className="text-gray-700">Суббота - Воскресенье: выходной</p>
</div>
</div>
</div>
</div>
{/* Map placeholder */}
<div className="mt-8">
<h3 className="text-lg font-semibold text-gray-900 mb-3">Местоположение</h3>
<div className="bg-gray-200 rounded-lg h-64 flex items-center justify-center">
<div className="text-center">
<span className="text-4xl text-gray-400 mb-2 block">🗺</span>
<p className="text-gray-600">Интерактивная карта</p>
<p className="text-sm text-gray-500">(будет добавлена позже)</p>
</div>
</div>
</div>
</div>
{/* Contact Form */}
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-6">Обратная связь</h2>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-2">
Имя *
</label>
<input
type="text"
id="name"
name="name"
required
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
value={formData.name}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
Email *
</label>
<input
type="email"
id="email"
name="email"
required
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="subject" className="block text-sm font-medium text-gray-700 mb-2">
Тема обращения *
</label>
<select
id="subject"
name="subject"
required
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
value={formData.subject}
onChange={handleChange}
>
<option value="">Выберите тему</option>
<option value="collaboration">Сотрудничество</option>
<option value="research">Исследования</option>
<option value="publications">Публикации</option>
<option value="education">Образование</option>
<option value="other">Другое</option>
</select>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-gray-700 mb-2">
Сообщение *
</label>
<textarea
id="message"
name="message"
required
rows={6}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-vertical"
value={formData.message}
onChange={handleChange}
placeholder="Опишите ваш вопрос или предложение..."
/>
</div>
<button
type="submit"
className="w-full bg-blue-600 text-white px-6 py-3 rounded-md hover:bg-blue-700 transition-colors font-medium"
>
Отправить сообщение
</button>
</form>
<div className="mt-6 p-4 bg-blue-50 rounded-lg">
<p className="text-sm text-blue-800">
<strong>Примечание:</strong> Мы отвечаем на все обращения в течение 1-2 рабочих дней.
Для срочных вопросов используйте телефон.
</p>
</div>
</div>
</div>
{/* Additional Information */}
<div className="mt-16 bg-gray-50 rounded-lg p-8">
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center">Направления сотрудничества</h2>
<div className="grid md:grid-cols-3 gap-6">
<div className="text-center">
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl">🔬</span>
</div>
<h3 className="text-lg font-semibold mb-2">Научные исследования</h3>
<p className="text-gray-600 text-sm">
Совместные исследования в области радиофотоники и оптических технологий
</p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl">🤝</span>
</div>
<h3 className="text-lg font-semibold mb-2">Промышленное партнерство</h3>
<p className="text-gray-600 text-sm">
Внедрение разработок и технологий в промышленные решения
</p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl">🎓</span>
</div>
<h3 className="text-lg font-semibold mb-2">Образование</h3>
<p className="text-gray-600 text-sm">
Образовательные программы, стажировки и подготовка кадров
</p>
</div>
</div>
</div>
</div>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,26 @@
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #171717;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}

View File

@ -0,0 +1,32 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
const inter = Inter({
subsets: ["latin", "cyrillic"],
});
export const metadata: Metadata = {
title: "Отдел Радиофотоники",
description: "Научно-исследовательский центр в области радиофотоники и оптических технологий",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="ru">
<body className={`${inter.className} antialiased min-h-screen flex flex-col`}>
<Header />
<main className="flex-1">
{children}
</main>
<Footer />
</body>
</html>
);
}

148
frontend/src/app/page.tsx Normal file
View File

@ -0,0 +1,148 @@
import Link from 'next/link';
import { mockNews, mockPublications, mockProjects } from '@/lib/mockData';
export default function Home() {
const latestNews = mockNews.slice(0, 2);
const recentPublications = mockPublications.slice(0, 3);
const activeProjects = mockProjects.filter(p => p.status === 'active').slice(0, 2);
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{/* Hero Section */}
<section className="text-center py-16 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg mb-12">
<h1 className="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
Отдел Радиофотоники
</h1>
<p className="text-xl text-gray-600 max-w-3xl mx-auto mb-8">
Ведущий научно-исследовательский центр в области радиофотоники и оптических технологий.
Мы занимаемся разработкой передовых решений для телекоммуникаций, сенсорики и обработки сигналов.
</p>
<div className="space-x-4">
<Link
href="/publications"
className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors inline-block"
>
Наши публикации
</Link>
<Link
href="/projects"
className="bg-white text-blue-600 border border-blue-600 px-6 py-3 rounded-lg hover:bg-blue-50 transition-colors inline-block"
>
Проекты
</Link>
</div>
</section>
{/* Latest News */}
<section className="mb-12">
<div className="flex justify-between items-center mb-6">
<h2 className="text-3xl font-bold text-gray-900">Последние новости</h2>
<Link href="/news" className="text-blue-600 hover:text-blue-800">
Все новости
</Link>
</div>
<div className="grid md:grid-cols-2 gap-6">
{latestNews.map(news => (
<div key={news.id} className="bg-white border rounded-lg p-6 shadow-sm hover:shadow-md transition-shadow">
<h3 className="text-xl font-semibold mb-3 text-gray-900">{news.title}</h3>
<p className="text-gray-600 mb-4 line-clamp-3">{news.content}</p>
<div className="flex justify-between items-center text-sm text-gray-500">
<span>{news.author}</span>
<span>{new Date(news.date).toLocaleDateString('ru-RU')}</span>
</div>
</div>
))}
</div>
</section>
{/* Recent Publications */}
<section className="mb-12">
<div className="flex justify-between items-center mb-6">
<h2 className="text-3xl font-bold text-gray-900">Последние публикации</h2>
<Link href="/publications" className="text-blue-600 hover:text-blue-800">
Все публикации
</Link>
</div>
<div className="grid gap-4">
{recentPublications.map(pub => (
<div key={pub.id} className="bg-white border rounded-lg p-6 shadow-sm hover:shadow-md transition-shadow">
<h3 className="text-lg font-semibold mb-2 text-gray-900">{pub.title}</h3>
<p className="text-gray-600 mb-2">
{pub.authors.join(', ')} {pub.journal} {pub.year}
</p>
<p className="text-gray-700 line-clamp-2">{pub.abstract}</p>
<div className="flex flex-wrap gap-2 mt-3">
{pub.tags.map(tag => (
<span key={tag} className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">
{tag}
</span>
))}
</div>
</div>
))}
</div>
</section>
{/* Active Projects */}
<section className="mb-12">
<div className="flex justify-between items-center mb-6">
<h2 className="text-3xl font-bold text-gray-900">Активные проекты</h2>
<Link href="/projects" className="text-blue-600 hover:text-blue-800">
Все проекты
</Link>
</div>
<div className="grid md:grid-cols-2 gap-6">
{activeProjects.map(project => (
<div key={project.id} className="bg-white border rounded-lg p-6 shadow-sm hover:shadow-md transition-shadow">
<div className="flex items-center justify-between mb-3">
<h3 className="text-xl font-semibold text-gray-900">{project.title}</h3>
<span className="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">
Активный
</span>
</div>
<p className="text-gray-700 mb-4 line-clamp-3">{project.description}</p>
<div className="text-sm text-gray-500">
<p>Период: {new Date(project.startDate).getFullYear()} - {project.endDate ? new Date(project.endDate).getFullYear() : 'н.в.'}</p>
{project.funding && <p>Финансирование: {project.funding}</p>}
</div>
</div>
))}
</div>
</section>
{/* Research Areas */}
<section className="bg-gray-50 rounded-lg p-8">
<h2 className="text-3xl font-bold text-gray-900 mb-8 text-center">Направления исследований</h2>
<div className="grid md:grid-cols-3 gap-6">
<div className="text-center">
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl">🔬</span>
</div>
<h3 className="text-xl font-semibold mb-3">Радиофотоника</h3>
<p className="text-gray-600">
Исследования в области взаимодействия оптических и микроволновых сигналов
</p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl">📡</span>
</div>
<h3 className="text-xl font-semibold mb-3">Оптические телекоммуникации</h3>
<p className="text-gray-600">
Разработка систем высокоскоростной передачи данных по оптическим каналам
</p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl"></span>
</div>
<h3 className="text-xl font-semibold mb-3">Квантовые технологии</h3>
<p className="text-gray-600">
Исследование квантовых эффектов в оптических системах и квантовых коммуникаций
</p>
</div>
</div>
</section>
</div>
);
}

View File

@ -0,0 +1,140 @@
import { mockProjects, mockStaff, mockPublications } from '@/lib/mockData';
import { Project } from '@/types';
export default function ProjectsPage() {
const activeProjects = mockProjects.filter(p => p.status === 'active');
const completedProjects = mockProjects.filter(p => p.status === 'completed');
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-4">Проекты</h1>
<p className="text-lg text-gray-600">
Исследовательские проекты и разработки отдела радиофотоники
</p>
</div>
{/* Active Projects */}
{activeProjects.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-gray-900 mb-6">Активные проекты</h2>
<div className="grid gap-6">
{activeProjects.map(project => (
<ProjectCard key={project.id} project={project} />
))}
</div>
</section>
)}
{/* Completed Projects */}
{completedProjects.length > 0 && (
<section>
<h2 className="text-2xl font-bold text-gray-900 mb-6">Завершенные проекты</h2>
<div className="grid gap-6">
{completedProjects.map(project => (
<ProjectCard key={project.id} project={project} />
))}
</div>
</section>
)}
</div>
);
}
function ProjectCard({ project }: { project: Project }) {
const teamMembers = mockStaff.filter(staff => project.team.includes(staff.id));
const projectPublications = mockPublications.filter(pub =>
project.publications.includes(pub.id)
);
const statusColors = {
active: 'bg-green-100 text-green-800',
completed: 'bg-blue-100 text-blue-800',
planned: 'bg-yellow-100 text-yellow-800'
};
const statusLabels = {
active: 'Активный',
completed: 'Завершен',
planned: 'Планируется'
};
return (
<div className="bg-white border rounded-lg p-6 shadow-sm hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<div className="flex items-center gap-3 mb-2">
<h3 className="text-2xl font-semibold text-gray-900">{project.title}</h3>
<span className={`text-xs px-2 py-1 rounded ${statusColors[project.status]}`}>
{statusLabels[project.status]}
</span>
</div>
<div className="text-sm text-gray-600 mb-4">
<span className="font-medium">Период:</span> {new Date(project.startDate).getFullYear()} - {project.endDate ? new Date(project.endDate).getFullYear() : 'н.в.'}
{project.funding && (
<span className="ml-4">
<span className="font-medium">Финансирование:</span> {project.funding}
</span>
)}
</div>
</div>
</div>
<div className="mb-6">
<p className="text-gray-700 leading-relaxed">{project.description}</p>
</div>
{/* Team */}
{teamMembers.length > 0 && (
<div className="mb-4">
<h4 className="text-sm font-semibold text-gray-900 mb-2">Команда проекта:</h4>
<div className="flex flex-wrap gap-2">
{teamMembers.map(member => (
<div key={member.id} className="bg-gray-100 rounded-lg px-3 py-1">
<p className="text-sm font-medium text-gray-900">{member.name}</p>
<p className="text-xs text-gray-600">{member.position}</p>
</div>
))}
</div>
</div>
)}
{/* Partners */}
{project.partners && project.partners.length > 0 && (
<div className="mb-4">
<h4 className="text-sm font-semibold text-gray-900 mb-2">Партнеры:</h4>
<div className="flex flex-wrap gap-2">
{project.partners.map(partner => (
<span
key={partner}
className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded"
>
{partner}
</span>
))}
</div>
</div>
)}
{/* Publications */}
{projectPublications.length > 0 && (
<div>
<h4 className="text-sm font-semibold text-gray-900 mb-2">
Публикации проекта ({projectPublications.length}):
</h4>
<div className="space-y-2">
{projectPublications.map(pub => (
<div key={pub.id} className="border-l-4 border-blue-200 pl-3">
<p className="text-sm font-medium text-gray-900">{pub.title}</p>
<p className="text-xs text-gray-600">
{pub.authors.join(', ')} {pub.journal} {pub.year}
</p>
</div>
))}
</div>
</div>
)}
</div>
);
}

View File

@ -0,0 +1,202 @@
'use client';
import { useState } from 'react';
import { mockPublications } from '@/lib/mockData';
import { Publication } from '@/types';
export default function PublicationsPage() {
const [searchTerm, setSearchTerm] = useState('');
const [selectedType, setSelectedType] = useState<string>('all');
const [selectedYear, setSelectedYear] = useState<string>('all');
const filteredPublications = mockPublications.filter(publication => {
const matchesSearch =
publication.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
publication.authors.some(author => author.toLowerCase().includes(searchTerm.toLowerCase())) ||
publication.journal.toLowerCase().includes(searchTerm.toLowerCase()) ||
publication.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
const matchesType = selectedType === 'all' || publication.type === selectedType;
const matchesYear = selectedYear === 'all' || publication.year.toString() === selectedYear;
return matchesSearch && matchesType && matchesYear;
});
const uniqueYears = Array.from(new Set(mockPublications.map(p => p.year))).sort((a, b) => b - a);
const uniqueTypes = Array.from(new Set(mockPublications.map(p => p.type)));
const typeLabels: Record<string, string> = {
'article': 'Статья',
'conference': 'Конференция',
'book': 'Книга',
'patent': 'Патент'
};
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-4">Публикации</h1>
<p className="text-lg text-gray-600">
Научные работы и публикации сотрудников отдела радиофотоники
</p>
</div>
{/* Search and Filters */}
<div className="bg-white border rounded-lg p-6 mb-8 shadow-sm">
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="md:col-span-2">
<label htmlFor="search" className="block text-sm font-medium text-gray-700 mb-2">
Поиск
</label>
<input
type="text"
id="search"
placeholder="Поиск по названию, авторам, журналу или тегам..."
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div>
<label htmlFor="type" className="block text-sm font-medium text-gray-700 mb-2">
Тип публикации
</label>
<select
id="type"
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
value={selectedType}
onChange={(e) => setSelectedType(e.target.value)}
>
<option value="all">Все типы</option>
{uniqueTypes.map(type => (
<option key={type} value={type}>{typeLabels[type] || type}</option>
))}
</select>
</div>
<div>
<label htmlFor="year" className="block text-sm font-medium text-gray-700 mb-2">
Год
</label>
<select
id="year"
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
value={selectedYear}
onChange={(e) => setSelectedYear(e.target.value)}
>
<option value="all">Все годы</option>
{uniqueYears.map(year => (
<option key={year} value={year.toString()}>{year}</option>
))}
</select>
</div>
</div>
<div className="mt-4 flex items-center justify-between">
<p className="text-sm text-gray-600">
Найдено публикаций: {filteredPublications.length} из {mockPublications.length}
</p>
{(searchTerm || selectedType !== 'all' || selectedYear !== 'all') && (
<button
onClick={() => {
setSearchTerm('');
setSelectedType('all');
setSelectedYear('all');
}}
className="text-sm text-blue-600 hover:text-blue-800"
>
Сбросить фильтры
</button>
)}
</div>
</div>
{/* Publications List */}
<div className="space-y-6">
{filteredPublications.length === 0 ? (
<div className="text-center py-12">
<p className="text-gray-500 text-lg">Публикации не найдены</p>
<p className="text-gray-400 text-sm mt-2">Попробуйте изменить параметры поиска</p>
</div>
) : (
filteredPublications.map(publication => (
<PublicationCard key={publication.id} publication={publication} />
))
)}
</div>
</div>
);
}
function PublicationCard({ publication }: { publication: Publication }) {
const typeLabels: Record<string, string> = {
'article': 'Статья',
'conference': 'Конференция',
'book': 'Книга',
'patent': 'Патент'
};
return (
<div className="bg-white border rounded-lg p-6 shadow-sm hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<div className="flex items-center gap-3 mb-2">
<h2 className="text-xl font-semibold text-gray-900">{publication.title}</h2>
<span className="bg-gray-100 text-gray-700 text-xs px-2 py-1 rounded">
{typeLabels[publication.type] || publication.type}
</span>
</div>
<p className="text-gray-600 mb-2">
<span className="font-medium">Авторы:</span> {publication.authors.join(', ')}
</p>
<p className="text-gray-600 mb-2">
<span className="font-medium">Журнал:</span> {publication.journal} {publication.year}
</p>
{publication.doi && (
<p className="text-gray-600 mb-2">
<span className="font-medium">DOI:</span>
<a href={`https://doi.org/${publication.doi}`} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800 ml-1">
{publication.doi}
</a>
</p>
)}
</div>
{publication.pdfUrl && (
<div className="ml-4">
<a
href={publication.pdfUrl}
target="_blank"
rel="noopener noreferrer"
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors text-sm"
>
PDF
</a>
</div>
)}
</div>
<div className="mb-4">
<p className="text-gray-700 leading-relaxed">{publication.abstract}</p>
</div>
<div className="flex flex-wrap gap-2">
{publication.tags.map(tag => (
<span
key={tag}
className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded hover:bg-blue-200 cursor-pointer transition-colors"
onClick={() => {
// В будущем можно добавить фильтрацию по тегам
}}
>
{tag}
</span>
))}
</div>
</div>
);
}

View File

@ -0,0 +1,110 @@
import { mockStaff, mockPublications } from '@/lib/mockData';
import { Staff } from '@/types';
import Image from 'next/image';
export default function StaffPage() {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-4">Сотрудники</h1>
<p className="text-lg text-gray-600">
Наша команда опытных исследователей и специалистов в области радиофотоники
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{mockStaff.map(staff => (
<StaffCard key={staff.id} staff={staff} />
))}
</div>
</div>
);
}
function StaffCard({ staff }: { staff: Staff }) {
const staffPublications = mockPublications.filter(pub =>
staff.publications.includes(pub.id)
);
return (
<div className="bg-white border rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow">
{/* Photo */}
<div className="relative h-64 bg-gray-200">
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/20 to-transparent" />
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-32 h-32 bg-gray-300 rounded-full flex items-center justify-center">
<span className="text-3xl text-gray-600">👤</span>
</div>
</div>
</div>
{/* Content */}
<div className="p-6">
<div className="mb-4">
<h3 className="text-xl font-semibold text-gray-900 mb-1">{staff.name}</h3>
<p className="text-blue-600 font-medium">{staff.position}</p>
<p className="text-sm text-gray-500">{staff.degree}</p>
</div>
<div className="mb-4">
<p className="text-gray-700 text-sm leading-relaxed">{staff.bio}</p>
</div>
{/* Contact Info */}
<div className="mb-4 space-y-2">
<div className="flex items-center text-sm text-gray-600">
<span className="w-4 h-4 mr-2">📧</span>
<a href={`mailto:${staff.email}`} className="hover:text-blue-600 transition-colors">
{staff.email}
</a>
</div>
{staff.phone && (
<div className="flex items-center text-sm text-gray-600">
<span className="w-4 h-4 mr-2">📞</span>
<a href={`tel:${staff.phone}`} className="hover:text-blue-600 transition-colors">
{staff.phone}
</a>
</div>
)}
</div>
{/* Research Interests */}
<div className="mb-4">
<h4 className="text-sm font-semibold text-gray-900 mb-2">Области исследований:</h4>
<div className="flex flex-wrap gap-1">
{staff.researchInterests.map(interest => (
<span
key={interest}
className="bg-gray-100 text-gray-700 text-xs px-2 py-1 rounded"
>
{interest}
</span>
))}
</div>
</div>
{/* Publications */}
{staffPublications.length > 0 && (
<div>
<h4 className="text-sm font-semibold text-gray-900 mb-2">
Публикации ({staffPublications.length}):
</h4>
<div className="space-y-2">
{staffPublications.slice(0, 2).map(pub => (
<div key={pub.id} className="text-xs text-gray-600">
<p className="font-medium text-gray-800 line-clamp-1">{pub.title}</p>
<p className="text-gray-500">{pub.journal}, {pub.year}</p>
</div>
))}
{staffPublications.length > 2 && (
<p className="text-xs text-blue-600">
и еще {staffPublications.length - 2} публикаций...
</p>
)}
</div>
</div>
)}
</div>
</div>
);
}

View File

@ -0,0 +1,35 @@
export default function Footer() {
return (
<footer className="bg-gray-800 text-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<h3 className="text-lg font-semibold mb-4">Отдел Радиофотоники</h3>
<p className="text-gray-300">
Ведущий научно-исследовательский центр в области радиофотоники и оптических технологий.
</p>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">Контакты</h3>
<div className="text-gray-300 space-y-2">
<p>📧 info@radiophotonics.ru</p>
<p>📞 +7 (495) 123-45-67</p>
<p>📍 Москва, ул. Научная, 1</p>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">Полезные ссылки</h3>
<div className="text-gray-300 space-y-2">
<p>🔗 Научные базы данных</p>
<p>🔗 Партнерские организации</p>
<p>🔗 Образовательные программы</p>
</div>
</div>
</div>
<div className="border-t border-gray-700 mt-8 pt-8 text-center text-gray-400">
<p>&copy; 2024 Отдел Радиофотоники. Все права защищены.</p>
</div>
</div>
</footer>
)
}

View File

@ -0,0 +1,41 @@
import Link from 'next/link'
export default function Header() {
return (
<header className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center">
<Link href="/" className="text-xl font-bold text-gray-900">
Отдел Радиофотоники
</Link>
</div>
<nav className="hidden md:flex space-x-8">
<Link href="/" className="text-gray-700 hover:text-blue-600 transition-colors">
Главная
</Link>
<Link href="/publications" className="text-gray-700 hover:text-blue-600 transition-colors">
Публикации
</Link>
<Link href="/staff" className="text-gray-700 hover:text-blue-600 transition-colors">
Сотрудники
</Link>
<Link href="/projects" className="text-gray-700 hover:text-blue-600 transition-colors">
Проекты
</Link>
<Link href="/contacts" className="text-gray-700 hover:text-blue-600 transition-colors">
Контакты
</Link>
</nav>
<div className="md:hidden">
<button className="text-gray-700 hover:text-blue-600">
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
</div>
</div>
</header>
)
}

View File

@ -0,0 +1,172 @@
import { Publication, Staff, Project, News, RID, Partner } from '@/types';
export const mockPublications: Publication[] = [
{
id: '1',
title: 'Когерентная обработка сигналов в радиофотонных системах',
authors: ['Иванов И.И.', 'Петров П.П.', 'Сидоров С.С.'],
journal: 'Квантовая электроника',
year: 2024,
abstract: 'В работе исследуются методы когерентной обработки сигналов в современных радиофотонных системах. Предложен новый алгоритм фазовой синхронизации, обеспечивающий высокую точность измерений.',
doi: '10.1070/QEL17XXX',
pdfUrl: '/uploads/publications/coherent-processing-2024.pdf',
tags: ['радиофотоника', 'когерентная обработка', 'фазовая синхронизация'],
type: 'article'
},
{
id: '2',
title: 'Микроволновые фотонные фильтры на основе кремниевых волноводов',
authors: ['Васильев В.В.', 'Козлов К.К.'],
journal: 'Оптика и спектроскопия',
year: 2024,
abstract: 'Разработаны и исследованы микроволновые фотонные фильтры на базе кремниевых волноводных структур. Достигнута высокая селективность и низкие оптические потери.',
doi: '10.1134/S0030400X24XXX',
pdfUrl: '/uploads/publications/photonic-filters-2024.pdf',
tags: ['фотонные фильтры', 'кремниевые волноводы', 'микроволновая фотоника'],
type: 'article'
},
{
id: '3',
title: 'Оптические генераторы миллиметрового диапазона для 5G/6G систем',
authors: ['Александров А.А.', 'Николаев Н.Н.', 'Федоров Ф.Ф.'],
journal: 'IEEE Photonics Technology Letters',
year: 2023,
abstract: 'Представлены результаты разработки оптических генераторов миллиметрового диапазона для применения в системах мобильной связи следующего поколения.',
doi: '10.1109/LPT.2023.XXXX',
pdfUrl: '/uploads/publications/mmwave-generators-2023.pdf',
tags: ['миллиметровые волны', '5G', '6G', 'оптические генераторы'],
type: 'article'
}
];
export const mockStaff: Staff[] = [
{
id: '1',
name: 'Иванов Иван Иванович',
position: 'Заведующий отделом',
email: 'ivanov@radiophotonics.ru',
phone: '+7 (495) 123-45-67',
photo: '/uploads/staff/ivanov.jpg',
bio: 'Доктор физико-математических наук, профессор. Специалист в области радиофотоники и оптических телекоммуникаций. Автор более 150 научных работ.',
publications: ['1', '2'],
researchInterests: ['радиофотоника', 'оптические телекоммуникации', 'когерентная оптика'],
degree: 'д.ф.-м.н.'
},
{
id: '2',
name: 'Петров Петр Петрович',
position: 'Ведущий научный сотрудник',
email: 'petrov@radiophotonics.ru',
phone: '+7 (495) 123-45-68',
photo: '/uploads/staff/petrov.jpg',
bio: 'Кандидат физико-математических наук. Специализируется на микроволновой фотонике и интегральной оптике.',
publications: ['1', '3'],
researchInterests: ['микроволновая фотоника', 'интегральная оптика', 'оптоэлектроника'],
degree: 'к.ф.-м.н.'
},
{
id: '3',
name: 'Сидорова Анна Сергеевна',
position: 'Старший научный сотрудник',
email: 'sidorova@radiophotonics.ru',
phone: '+7 (495) 123-45-69',
photo: '/uploads/staff/sidorova.jpg',
bio: 'Кандидат технических наук. Работает в области фотонных сенсоров и оптических измерительных систем.',
publications: ['2'],
researchInterests: ['фотонные сенсоры', 'оптические измерения', 'волоконная оптика'],
degree: 'к.т.н.'
}
];
export const mockProjects: Project[] = [
{
id: '1',
title: 'Разработка радиофотонных систем для 6G сетей',
description: 'Исследование и создание передовых радиофотонных технологий для беспроводных сетей шестого поколения, обеспечивающих высокую скорость передачи данных и низкую задержку.',
status: 'active',
startDate: '2023-01-01',
endDate: '2025-12-31',
team: ['1', '2', '3'],
publications: ['3'],
partners: ['Huawei', 'Nokia'],
funding: 'РФФИ, грант №23-07-00123',
image: '/uploads/projects/6g-networks.jpg'
},
{
id: '2',
title: 'Квантовые коммуникации на основе фотонных кристаллов',
description: 'Разработка новых подходов к квантовым коммуникациям с использованием фотонных кристаллических структур для повышения безопасности передачи информации.',
status: 'active',
startDate: '2022-06-01',
endDate: '2024-12-31',
team: ['1', '3'],
publications: ['1', '2'],
funding: 'РНФ, грант №22-12-00456',
image: '/uploads/projects/quantum-comm.jpg'
}
];
export const mockNews: News[] = [
{
id: '1',
title: 'Отдел радиофотоники получил грант РНФ на исследование квантовых коммуникаций',
content: 'Коллектив отдела успешно выиграл конкурс Российского научного фонда и получил финансирование на трехлетний проект по разработке квантовых коммуникационных систем.',
date: '2024-01-15',
author: 'Иванов И.И.',
image: '/uploads/news/grant-rnf.jpg',
tags: ['гранты', 'квантовые коммуникации', 'РНФ']
},
{
id: '2',
title: 'Публикация в высокорейтинговом журнале IEEE',
content: 'Статья сотрудников отдела о микроволновых фотонных фильтрах опубликована в престижном международном журнале IEEE Photonics Technology Letters.',
date: '2024-02-10',
author: 'Петров П.П.',
image: '/uploads/news/ieee-publication.jpg',
tags: ['публикации', 'IEEE', 'фотонные фильтры']
}
];
export const mockRIDs: RID[] = [
{
id: '1',
title: 'Способ формирования радиофотонного сигнала с низким фазовым шумом',
type: 'patent',
registrationNumber: 'RU 2745123 C1',
registrationDate: '2021-03-22',
authors: ['Иванов И.И.', 'Петров П.П.'],
description: 'Изобретение относится к области радиофотоники и может быть использовано для создания высокостабильных генераторов.',
status: 'registered'
},
{
id: '2',
title: 'Программа моделирования фотонных интегральных схем',
type: 'software',
registrationNumber: '2023612345',
registrationDate: '2023-04-15',
authors: ['Сидорова А.С.', 'Васильев В.В.'],
description: 'Программное обеспечение для проектирования и моделирования фотонных интегральных схем.',
status: 'registered'
}
];
export const mockPartners: Partner[] = [
{
id: '1',
name: 'Huawei Technologies',
logo: '/uploads/partners/huawei-logo.png',
website: 'https://www.huawei.com',
description: 'Совместные исследования в области 5G/6G технологий и радиофотоники.',
collaborationType: ['исследования', 'разработка'],
projects: ['1']
},
{
id: '2',
name: 'ООО "ОптЛинк"',
logo: '/uploads/partners/optlink-logo.png',
website: 'https://optlink.ru',
description: 'Российская компания, специализирующаяся на производстве оптоэлектронных компонентов.',
collaborationType: ['производство', 'внедрение'],
projects: ['2']
}
];

View File

@ -0,0 +1,70 @@
export interface Publication {
id: string;
title: string;
authors: string[];
journal: string;
year: number;
abstract: string;
doi?: string;
pdfUrl?: string;
tags: string[];
type: 'article' | 'conference' | 'book' | 'patent';
}
export interface Staff {
id: string;
name: string;
position: string;
email: string;
phone?: string;
photo: string;
bio: string;
publications: string[];
researchInterests: string[];
degree: string;
}
export interface Project {
id: string;
title: string;
description: string;
status: 'active' | 'completed' | 'planned';
startDate: string;
endDate?: string;
team: string[];
publications: string[];
partners?: string[];
funding?: string;
image?: string;
}
export interface News {
id: string;
title: string;
content: string;
date: string;
author: string;
image?: string;
tags: string[];
}
export interface RID {
id: string;
title: string;
type: 'patent' | 'software' | 'database' | 'method';
registrationNumber?: string;
registrationDate?: string;
authors: string[];
description: string;
status: 'registered' | 'pending' | 'application';
}
export interface Partner {
id: string;
name: string;
logo: string;
website?: string;
description: string;
collaborationType: string[];
projects: string[];
}

27
frontend/tsconfig.json Normal file
View File

@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}