Compare commits
55 Commits
18f2984bbc
...
main
Author | SHA1 | Date | |
---|---|---|---|
4ccbd28c4f | |||
618e5b442e | |||
936a2fa1ee | |||
2165a63bfb | |||
2d294de69a | |||
7754370a70 | |||
2edf6b3f1f | |||
8b0996781e | |||
bb714e6fa2 | |||
75f516b408 | |||
8403a17636 | |||
44353988a1 | |||
1d3d684c8f | |||
86e145515e | |||
fca8d962f4 | |||
19cc813de7 | |||
2579460c1f | |||
afec14c390 | |||
c4bf7c8b20 | |||
0c3b2bf81d | |||
881f832722 | |||
73e022212f | |||
af27b23c2f | |||
d38947d316 | |||
33f68a7e49 | |||
ecd3fa120d | |||
38d01821b2 | |||
6471ffb916 | |||
6e1de4b48f | |||
20dfb50ac8 | |||
b8e8057442 | |||
8df4c91907 | |||
26dd1c45a3 | |||
95bc368ebb | |||
36bb04cfa9 | |||
d6e6b1ccb4 | |||
184d31c07f | |||
e10d46b5a1 | |||
b77736b88f | |||
cebad8a7b0 | |||
e0ad21cc2b | |||
5045a342b5 | |||
d107630ae4 | |||
cf01e429e4 | |||
204ea4f4bc | |||
ccca533db6 | |||
153f5fd146 | |||
ff30258377 | |||
0cb192ef81 | |||
ca4ec57666 | |||
9bb8196ed0 | |||
98f587ccbc | |||
846822ed41 | |||
bb1d778600 | |||
4bb7f4c979 |
311
README.md
311
README.md
@@ -1,92 +1,269 @@
|
||||
<img src="https://r2cdn.perplexity.ai/pplx-full-logo-primary-dark%402x.png" class="logo" width="120"/>
|
||||
# REMind - Dream Analysis & VR Experience Platform
|
||||
|
||||
# REMind (Mockup Demo)
|
||||

|
||||

|
||||

|
||||
|
||||
🚧 **This is a MOCKUP / DEMO APPLICATION for a university project – no real backend, AI features, or data storage.** 🚧
|
||||
> **🚧 IMPORTANT: This is a MOCKUP/DEMO APPLICATION for a university project**
|
||||
> **No real backend, AI features, or data storage. All functionality is simulated for demonstration purposes.**
|
||||
|
||||
REMind is an interactive, front-end prototype that showcases dream journaling, AI-powered analysis (simulated), and immersive VR demonstrations. Built with React, TypeScript, Vite, and Tailwind CSS, it’s designed for demos and concept validation only.
|
||||
## Project Overview
|
||||
|
||||
## Features (all mockup/demo only)
|
||||
REMind is an innovative interactive prototype that explores the intersection of dream analysis, artificial intelligence,
|
||||
and virtual reality. The application demonstrates how modern technology could revolutionize dream journaling and
|
||||
interpretation through immersive experiences and intelligent analysis.
|
||||
|
||||
- **(Mockup)** Dream Journal
|
||||
Record dreams as text entries, voice memos, or sketches—UI only, no persistence.
|
||||
- **(Mockup)** AI Analysis
|
||||
Simulated “Here the AI would analyze your dream…” step with instant, hard-coded interpretations, symbol recognition, and emotion tagging.
|
||||
- **(Mockup)** Personal Archive
|
||||
Browse and filter past mock entries by date, symbols, emotions, or tags.
|
||||
- **(Mockup)** Statistics \& Trends
|
||||
Visualize frequent symbols, emotional patterns, and simulated sleep-cycle correlations using dummy data.
|
||||
- **(Mockup)** VR Dreamscapes
|
||||
Enter 3D scenes built with React Three Fiber—explore thematic environments (labyrinths, dark rooms) in browser-based VR mode.
|
||||
- **Responsive Design**
|
||||
Works on desktop browsers(design optimized for mobile) and mobile devices. Ideal for QR-code launches at demos.
|
||||
**Project Aim:** To showcase the potential of combining dream journaling with AI-powered analysis and VR visualization,
|
||||
creating an engaging platform for understanding the subconscious mind and exploring the societal implications of dream
|
||||
research.
|
||||
|
||||
## Tech Stack
|
||||
## ✨ Key Features
|
||||
|
||||
- **Framework:** React + TypeScript
|
||||
- **Bundler:** Vite
|
||||
- **Styling:** Tailwind CSS
|
||||
- **Routing:** React Router Dom
|
||||
- **Icons:** React Icons
|
||||
- **3D \& VR:** @react-three/fiber
|
||||
- **Linting:** ESLint
|
||||
### 🌙 Multi-Modal Dream Recording
|
||||
|
||||
## Getting Started
|
||||
- **Text Input**: Write detailed dream descriptions with rich formatting
|
||||
- **Voice Recording**: Record dream narratives with audio transcription
|
||||
- **Image Upload**: Upload dream sketches, drawings, or related images
|
||||
- **Biometric Integration**: Simulate EEG, heart rate, and movement data from sleep tracking devices
|
||||
|
||||
> **Note:** This repository contains only a front-end prototype with hard-coded mock data. There is no production backend or AI service.
|
||||
### 🤖 AI-Powered Analysis (Simulated)
|
||||
|
||||
1. Clone the repo
|
||||
- **Symbol Recognition**: Identify and categorize dream symbols
|
||||
- **Emotion Detection**: Analyze emotional patterns and mood indicators
|
||||
- **Interpretation Engine**: Generate personalized dream interpretations
|
||||
- **Pattern Analysis**: Detect recurring themes and symbols across dreams
|
||||
|
||||
```bash
|
||||
git clone https://gitea.puchstein.bayern/mpuchstein/REMind.git
|
||||
cd REMind
|
||||
```
|
||||
### 🎮 VR Dreamscapes
|
||||
|
||||
2. Install dependencies
|
||||
- **3D Visualization**: Transform dreams into immersive 3D environments
|
||||
- **Neural Network Visualization**: Interactive neural network representations for biometric data
|
||||
- **VR Experience**: WebXR-enabled virtual reality exploration
|
||||
- **Responsive Controls**: Support for both VR headsets and desktop interaction
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
### 📊 Advanced Analytics
|
||||
|
||||
3. Run development server
|
||||
- **EEG Visualization**: Real-time brainwave pattern charts (Alpha, Beta, Theta, Delta)
|
||||
- **Vital Signs Monitoring**: Heart rate and HRV trend analysis
|
||||
- **Movement Tracking**: Sleep movement pattern visualization
|
||||
- **Statistical Dashboard**: Comprehensive dream pattern analysis
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
### 🗂️ Dream Archive & Management
|
||||
|
||||
Open `http://localhost:5173` in your browser. 4. Build for production (static demo)
|
||||
- **Personal Library**: Organized collection of all dream entries
|
||||
- **Search & Filter**: Advanced filtering by date, symbols, emotions, and tags
|
||||
- **Social Features**: Share dreams with friends and community
|
||||
- **Daily Highlights**: Curated dream insights and patterns
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run preview
|
||||
```
|
||||
### 🌐 Community Features
|
||||
|
||||
## Project Structure
|
||||
- **Dream Archive**: Explore categorized dream collections
|
||||
- **Research Integration**: Live research data visualization
|
||||
- **Cultural Landscapes**: Dreams categorized by cultural themes
|
||||
- **Worldwide Events**: Global dream pattern analysis
|
||||
|
||||
## 🛠️ Technology Stack
|
||||
|
||||
### Frontend Framework
|
||||
|
||||
- **React 19.1.0** - Modern React with latest features
|
||||
- **TypeScript** - Type-safe development
|
||||
- **Vite 7.0.0** - Fast build tool and development server
|
||||
|
||||
### Styling & UI
|
||||
|
||||
- **Tailwind CSS 4.1.11** - Utility-first CSS framework
|
||||
- **CSS Variables** - Dynamic theming system
|
||||
- **Responsive Design** - Mobile-first approach
|
||||
|
||||
### 3D & VR
|
||||
|
||||
- **Three.js 0.178.0** - 3D graphics library
|
||||
- **@react-three/fiber 9.2.0** - React Three.js renderer
|
||||
- **@react-three/drei 10.5.1** - Three.js helpers
|
||||
- **@react-three/xr 6.6.19** - WebXR integration
|
||||
- **webxr-polyfill 2.0.3** - VR compatibility
|
||||
|
||||
### Data Visualization
|
||||
|
||||
- **D3.js 7.9.0** - Advanced data visualization
|
||||
- **Custom Chart Components** - EEG, vitals, and movement charts
|
||||
|
||||
### Navigation & Routing
|
||||
|
||||
- **React Router DOM 7.6.3** - Client-side routing
|
||||
- **React Icons 5.5.0** - Comprehensive icon library
|
||||
|
||||
### Development Tools
|
||||
|
||||
- **ESLint** - Code linting and formatting
|
||||
- **TypeScript ESLint** - TypeScript-specific linting
|
||||
- **Vite Plugin React** - React integration
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── public/ # Static assets
|
||||
REMind/
|
||||
├── public/ # Static assets (favicon, etc.)
|
||||
├── src/
|
||||
│ ├── assets/ # Images, fonts
|
||||
│ ├── components/ # Reusable React components
|
||||
│ ├── data/ # Mock data (dream entries, analysis)
|
||||
│ ├── pages/ # Route-driven pages
|
||||
│ ├── types/ # TypeScript types/interfaces
|
||||
│ ├── App.tsx # Root component
|
||||
│ ├── index.css # Tailwind setup
|
||||
│ └── main.tsx # Entry point
|
||||
├── index.html # HTML template
|
||||
├── package.json # Scripts & dependencies
|
||||
├── tsconfig.app.json # TS config for app
|
||||
├── vite.config.ts # Vite config
|
||||
└── README.md # This file
|
||||
│ ├── assets/ # Images, logos, fonts
|
||||
│ ├── components/ # Reusable UI components
|
||||
│ │ ├── DreamCard.tsx # Dream display component
|
||||
│ │ ├── DreamRecord.tsx # Dream recording interface
|
||||
│ │ ├── DreamVR.tsx # VR visualization component
|
||||
│ │ ├── DreamCharts.tsx # Data visualization components
|
||||
│ │ ├── Navbar.tsx # Navigation component
|
||||
│ │ └── ...
|
||||
│ ├── data/ # Mock data for demonstration
|
||||
│ │ ├── MockDreams.ts # Sample dream entries
|
||||
│ │ ├── MockUsers.ts # User data
|
||||
│ │ └── ...
|
||||
│ ├── pages/ # Route-driven page components
|
||||
│ │ ├── Home.tsx # Main dashboard
|
||||
│ │ ├── Feed.tsx # Dream feed
|
||||
│ │ ├── DreamPage.tsx # Individual dream view
|
||||
│ │ ├── Overview.tsx # Landing page
|
||||
│ │ └── dreamarchive/ # Archive pages
|
||||
│ ├── types/ # TypeScript type definitions
|
||||
│ │ ├── Dream.ts # Dream data structures
|
||||
│ │ └── User.ts # User data structures
|
||||
│ ├── utils/ # Utility functions
|
||||
│ ├── styles/ # Styling utilities
|
||||
│ ├── App.tsx # Root component
|
||||
│ ├── main.tsx # Application entry point
|
||||
│ └── index.css # Global styles
|
||||
├── docs/ # Documentation
|
||||
│ └── poster.pdf # Project presentation poster
|
||||
├── package.json # Dependencies and scripts
|
||||
├── tsconfig.app.json # TypeScript configuration
|
||||
├── vite.config.ts # Vite configuration
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Usage \& Demo
|
||||
## 🚀 Getting Started
|
||||
|
||||
- **Start Dream Journal** — click “🌙 Lass die Magie beginnen” to open the mock dream entry form.
|
||||
- **AI Analysis** — submit an entry to see the “mock” interpretation card.
|
||||
- **Browse Archive** — filter mock entries by symbol, emotion, or date.
|
||||
- **VR Mode** — click VR Demo to load an immersive 3D scene in your browser.
|
||||
### Prerequisites
|
||||
|
||||
**Reminder:** REMind is a design-and-concept prototype only. Enjoy exploring the features—no real data or AI integration under the hood!
|
||||
- Node.js 18+
|
||||
- npm or yarn package manager
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Clone the repository**
|
||||
```bash
|
||||
git clone https://gitea.puchstein.bayern/mpuchstein/REMind.git
|
||||
cd REMind
|
||||
```
|
||||
|
||||
2. **Install dependencies**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. **Start development server**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
4. **Open in browser**
|
||||
```
|
||||
http://localhost:5173
|
||||
```
|
||||
|
||||
### Available Scripts
|
||||
|
||||
- `npm run dev` - Start development server
|
||||
- `npm run build` - Build for production
|
||||
- `npm run preview` - Preview production build
|
||||
- `npm run lint` - Run ESLint
|
||||
|
||||
## 🎯 Usage Guide
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. **Landing Page**: Visit the overview page to understand the application concept
|
||||
2. **Begin Journey**: Click "Lass die Magie beginnen" to start the dream recording experience
|
||||
3. **Record Dreams**: Use various input methods (text, voice, image, biometric)
|
||||
4. **AI Analysis**: View simulated AI interpretations and insights
|
||||
5. **VR Experience**: Explore dreams in virtual reality environments
|
||||
6. **Archive Exploration**: Browse and filter through dream collections
|
||||
|
||||
### Key Navigation
|
||||
|
||||
- **Home** (`/home`) - Personal dashboard with recent dreams
|
||||
- **Feed** (`/feed`) - Community dream sharing
|
||||
- **Record** (`/record`) - Dream input interface
|
||||
- **Dream Archive** (`/dreamarchive`) - Categorized dream collections
|
||||
- **Profile** (`/profile`) - User settings and statistics
|
||||
|
||||
### Input Types
|
||||
|
||||
- **Text**: Write detailed dream descriptions
|
||||
- **Audio**: Record voice memos with transcription
|
||||
- **Image**: Upload dream-related visuals
|
||||
- **Chip**: Biometric data from sleep tracking devices
|
||||
|
||||
## 🔮 Demo Features
|
||||
|
||||
### Simulated AI Analysis
|
||||
|
||||
- **Symbol Recognition**: Identifies dream symbols like "water," "flying," "animals"
|
||||
- **Emotion Tagging**: Categorizes emotions as "fear," "joy," "anxiety," "peace"
|
||||
- **Interpretation**: Generates psychological insights and meanings
|
||||
- **Pattern Detection**: Highlights recurring themes across dreams
|
||||
|
||||
### VR Visualization
|
||||
|
||||
- **Neural Networks**: Interactive 3D representations of brain activity
|
||||
- **Dreamscapes**: Immersive environments based on dream content
|
||||
- **Data Visualization**: 3D charts and graphs for biometric data
|
||||
- **WebXR Support**: Compatible with VR headsets and desktop browsers
|
||||
|
||||
### Data Analytics
|
||||
|
||||
- **EEG Patterns**: Brainwave analysis during sleep (Alpha, Beta, Theta, Delta)
|
||||
- **Vital Signs**: Heart rate and heart rate variability trends
|
||||
- **Movement Data**: Sleep movement and restlessness patterns
|
||||
- **Statistical Insights**: Long-term pattern analysis and correlations
|
||||
|
||||
## ⚠️ Important Notes
|
||||
|
||||
### Assets Not Included
|
||||
|
||||
- **Media Files**: Dream images, audio files, and videos are not included in the repository
|
||||
- **Mock Data**: All displayed content uses placeholder data for demonstration
|
||||
- **External Resources**: Some images and media are referenced but not stored in the repository
|
||||
|
||||
### Limitations
|
||||
|
||||
- **No Backend**: All data is stored locally in browser memory
|
||||
- **No AI Integration**: Analysis results are pre-generated mock responses
|
||||
- **No Data Persistence**: Data is lost when browser is refreshed
|
||||
- **Demo Purpose Only**: Not intended for production use
|
||||
|
||||
## 🎓 Educational Context
|
||||
|
||||
This project was developed as a university demonstration to explore:
|
||||
|
||||
- **Human-Computer Interaction**: Innovative interfaces for dream recording
|
||||
- **Data Visualization**: Advanced techniques for complex data representation
|
||||
- **Virtual Reality**: Immersive experiences for psychological content
|
||||
- **AI Integration**: Simulated machine learning for content analysis
|
||||
- **User Experience**: Intuitive design for sensitive personal data
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
This is a university project demo and not actively maintained for production use. However, feedback and suggestions are
|
||||
welcome for educational purposes.
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the AGPL-3.0 License - see the LICENSE file for details.
|
||||
|
||||
## 🔗 Repository
|
||||
|
||||
[View on Gitea](https://gitea.puchstein.bayern/mpuchstein/REMind)
|
||||
|
||||
---
|
||||
|
||||
**Disclaimer**: REMind is a prototype demonstration created for educational purposes. All AI features, data analysis,
|
||||
and interpretations are simulated and should not be used for actual psychological or medical analysis.
|
BIN
docs/poster.pdf
Normal file
BIN
docs/poster.pdf
Normal file
Binary file not shown.
1981
package-lock.json
generated
1981
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -10,20 +10,30 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^10.5.1",
|
||||
"@react-three/fiber": "^9.2.0",
|
||||
"@react-three/xr": "^6.6.19",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"d3": "^7.9.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router-dom": "^7.6.3",
|
||||
"react-slick": "^0.30.3",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"tailwindcss": "^4.1.11"
|
||||
"tailwindcss": "^4.1.11",
|
||||
"three": "^0.178.0",
|
||||
"webxr-polyfill": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.29.0",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/node": "^24.0.14",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"@types/react-slick": "^0.23.13",
|
||||
"@types/three": "^0.178.1",
|
||||
"@types/webxr": "^0.5.22",
|
||||
"@vitejs/plugin-react": "^4.5.2",
|
||||
"eslint": "^9.29.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
34
src/App.css
34
src/App.css
@@ -97,3 +97,37 @@
|
||||
box-shadow: 0 15px 35px var(--shadow), inset 0 0 20px rgba(255, 255, 255, 0.3);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Carousel controls styling */
|
||||
.carousel-container .slick-prev,
|
||||
.carousel-container .slick-next {
|
||||
z-index: 10;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: rgba(166, 77, 255, 0.7);
|
||||
border-radius: 50%;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.carousel-container .slick-prev {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.carousel-container .slick-next {
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.carousel-container .slick-prev:hover,
|
||||
.carousel-container .slick-next:hover {
|
||||
background: rgba(166, 77, 255, 0.9);
|
||||
}
|
||||
|
||||
.carousel-container .slick-prev:before,
|
||||
.carousel-container .slick-next:before {
|
||||
font-size: 20px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
132
src/App.tsx
132
src/App.tsx
@@ -9,111 +9,16 @@ import DreamPage from "./pages/DreamPage.tsx";
|
||||
import ProfilePage from "./pages/ProfilePage.tsx";
|
||||
import Home from "./pages/Home.tsx";
|
||||
import Overview from "./pages/Overview.tsx";
|
||||
|
||||
function Record() {
|
||||
return (
|
||||
<div className="p-4">
|
||||
<h1 className="dreamy-text text-3xl md:text-4xl mb-6">Record Your Dream</h1>
|
||||
|
||||
<div className="dream-container">
|
||||
<div className="flex flex-col items-center mb-6">
|
||||
<div className="w-20 h-20 rounded-full flex items-center justify-center mb-4 floating"
|
||||
style={{ background: 'var(--accent-gradient)' }}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-lg mb-2">Tap to start recording your dream</p>
|
||||
<p className="text-sm text-center" style={{ color: 'var(--text-muted)' }}>
|
||||
Your voice will be transcribed automatically
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="dreamy-border p-4 mb-6">
|
||||
<textarea
|
||||
className="w-full p-3 rounded-lg bg-transparent focus:outline-none"
|
||||
placeholder="Or type your dream here..."
|
||||
rows={5}
|
||||
style={{ color: 'var(--text)', borderColor: 'var(--accent-soft)' }}
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<button className="dreamy-button w-full">Save Dream</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Archive() {
|
||||
return (
|
||||
<div className="p-4">
|
||||
<h1 className="dreamy-text text-3xl md:text-4xl mb-6">Dream Archive</h1>
|
||||
|
||||
<div className="mb-6 flex flex-col sm:flex-row gap-4">
|
||||
<div className="flex-1">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search dreams..."
|
||||
className="w-full p-3 rounded-lg focus:outline-none"
|
||||
style={{
|
||||
backgroundColor: 'var(--container)',
|
||||
color: 'var(--text)',
|
||||
borderColor: 'var(--accent-soft)',
|
||||
boxShadow: '0 2px 8px var(--shadow)'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<select
|
||||
className="w-full p-3 rounded-lg focus:outline-none"
|
||||
style={{
|
||||
backgroundColor: 'var(--container)',
|
||||
color: 'var(--text)',
|
||||
borderColor: 'var(--accent-soft)',
|
||||
boxShadow: '0 2px 8px var(--shadow)'
|
||||
}}
|
||||
>
|
||||
<option>All Dreams</option>
|
||||
<option>Last Week</option>
|
||||
<option>Last Month</option>
|
||||
<option>Last Year</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{[1, 2, 3].map((item) => (
|
||||
<div key={item} className="card">
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<h3 className="text-xl font-bold" style={{ color: 'var(--accent)' }}>
|
||||
Dream #{item}
|
||||
</h3>
|
||||
<span style={{ color: 'var(--text-muted)' }}>
|
||||
{new Date().toLocaleDateString()}
|
||||
</span>
|
||||
</div>
|
||||
<p className="mb-4">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Vivamus lacinia, nunc eu tincidunt faucibus...
|
||||
</p>
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
className="px-4 py-2 rounded-lg transition-transform hover:scale-105"
|
||||
style={{
|
||||
background: 'var(--accent-gradient)',
|
||||
color: 'white'
|
||||
}}
|
||||
>
|
||||
View Details
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
import ChipOverview from "./pages/ChipOverview.tsx";
|
||||
import DreamArchiveIndex from "./pages/dreamarchive/DreamArchiveIndex.tsx";
|
||||
import WorldwideEvents from "./pages/dreamarchive/WorldwideEvents.tsx";
|
||||
import CulturalLandscapes from "./pages/dreamarchive/CulturalLandscapes.tsx";
|
||||
import LivingConditions from "./pages/dreamarchive/LivingConditions.tsx";
|
||||
import Technology from "./pages/dreamarchive/Technology.tsx";
|
||||
import UserDreams from "./pages/dreamarchive/UserDreams.tsx";
|
||||
import ResearchLive from "./pages/dreamarchive/ResearchLive.tsx";
|
||||
import ScrollToTop from "./components/ScrollToTop.tsx";
|
||||
import {DreamRecord} from "./components/DreamRecord.tsx";
|
||||
|
||||
export default function App() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@@ -129,12 +34,20 @@ export default function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<BrowserRouter>
|
||||
<ScrollToTop/>
|
||||
<AppContent/>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Record() {
|
||||
return (
|
||||
<div className="page p-4 space-y-6">
|
||||
<DreamRecord/>
|
||||
</div>)
|
||||
}
|
||||
|
||||
// Separate component to use useLocation hook
|
||||
function AppContent() {
|
||||
const location = useLocation();
|
||||
@@ -150,8 +63,15 @@ function AppContent() {
|
||||
<Route path="/" element={<Overview/>}/>
|
||||
<Route path="/home" element={<Home/>}/>
|
||||
<Route path="/feed" element={<Feed/>}/>
|
||||
<Route path="/chip" element={<ChipOverview/>}/>
|
||||
<Route path="/record" element={<Record/>}/>
|
||||
<Route path="/archive" element={<Archive/>}/>
|
||||
<Route path="/dreamarchive" element={<DreamArchiveIndex/>}/>
|
||||
<Route path="/dreamarchive/worldwide-events" element={<WorldwideEvents/>}/>
|
||||
<Route path="/dreamarchive/cultural-landscapes" element={<CulturalLandscapes/>}/>
|
||||
<Route path="/dreamarchive/living-conditions" element={<LivingConditions/>}/>
|
||||
<Route path="/dreamarchive/technology" element={<Technology/>}/>
|
||||
<Route path="/dreamarchive/user-dreams" element={<UserDreams/>}/>
|
||||
<Route path="/dreamarchive/research-live" element={<ResearchLive/>}/>
|
||||
<Route path="/profile" element={<ProfilePage/>}/>
|
||||
<Route path="/dream/:id" element={<DreamPage/>}/>
|
||||
</Routes>
|
||||
|
21
src/assets/logotext_dark.svg
Normal file
21
src/assets/logotext_dark.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<svg width="400" height="120" viewBox="0 0 400 120" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="moonGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0" stop-color="#a64dff"/>
|
||||
<stop offset="100" stop-color="#6a0dad"/>
|
||||
</linearGradient>
|
||||
<mask id="moonMask">
|
||||
<circle cx="60" cy="60" r="50" fill="white"/>
|
||||
<circle cx="75" cy="40" r="45" fill="black"/>
|
||||
</mask>
|
||||
<style type="text/css">
|
||||
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap');
|
||||
</style>
|
||||
</defs>
|
||||
<circle cx="60" cy="60" r="60" fill="url(#moonGradient)" mask="url(#moonMask)"/>
|
||||
<text x="250" y="60%" dominant-baseline="middle" text-anchor="middle"
|
||||
font-family="'Raleway', sans-serif" font-size="70" fill="black" letter-spacing="2"
|
||||
style="text-shadow: 0 0 5px rgba(0,0,0,0.3);">
|
||||
REMind
|
||||
</text>
|
||||
</svg>
|
After Width: | Height: | Size: 982 B |
@@ -4,8 +4,8 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap');
|
||||
</style>
|
||||
<linearGradient id="textGradient" x1="25%" y1="0%" x2="75%" y2="100%">
|
||||
<stop offset="0%" stop-color="darkslateblue" />
|
||||
<stop offset="100%" stop-color="indigo" />
|
||||
<stop offset="0%" stop-color="white"/>
|
||||
<stop offset="100%" stop-color="grey"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
|
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 707 B |
40
src/components/ChipCard.tsx
Normal file
40
src/components/ChipCard.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import {NavLink} from 'react-router-dom';
|
||||
|
||||
export const ChipCard: React.FC = () => {
|
||||
return (
|
||||
<NavLink to="/chip"
|
||||
className="block transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] animate-fadeIn rounded-lg mb-4 floating">
|
||||
<div
|
||||
className="p-4 backdrop-blur-sm rounded-lg"
|
||||
style={{
|
||||
background: 'var(--purple-gradient)',
|
||||
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.2)',
|
||||
border: '1px solid rgba(166, 77, 255, 0.1)'
|
||||
}}>
|
||||
<div className="flex flex-col sm:flex-row items-center">
|
||||
<div
|
||||
className="mb-4 sm:mb-0 sm:mr-4 transition-all duration-300 hover:transform hover:rotate-12">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-16 w-16" fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1}
|
||||
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-bold text-lg mb-1 dream-title">ReMind Sensor-Gerät</h3>
|
||||
<p className="text-sm mb-2">Verbessere deine Traumerfahrung mit unserem Sensor
|
||||
mit EEG,
|
||||
Bewegungserkennung und Vitalzeichen-Überwachung.</p>
|
||||
<div
|
||||
className="mb-3 inline-block px-2 py-1 text-xs font-bold rounded transition-all duration-300 hover:transform hover:scale-105"
|
||||
style={{backgroundColor: 'var(--accent-soft)', color: 'var(--text)'}}>
|
||||
Pro-Funktionen: VR-Räume, Automatische Traumerkennung und Aufzeichnung
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
);
|
||||
};
|
102
src/components/DailyHighlights.tsx
Normal file
102
src/components/DailyHighlights.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import {primaryMoodCategories, topDreamTopics} from '../data/MockDailyHighlights';
|
||||
import {getTextStyle} from '../styles/StyleUtils';
|
||||
|
||||
/**
|
||||
* HighlightCard component displays a single highlight item with a colored progress bar
|
||||
*/
|
||||
interface HighlightItemProps {
|
||||
label: string;
|
||||
percentage: number;
|
||||
}
|
||||
|
||||
const HighlightCard = ({label, percentage}: HighlightItemProps) => {
|
||||
return (
|
||||
<div
|
||||
className="mb-3 rounded-lg overflow-hidden shadow-md hover:shadow-lg transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] animate-fadeIn floating">
|
||||
<div className="relative p-4 backdrop-blur-sm"
|
||||
style={{
|
||||
background: 'var(--purple-gradient)',
|
||||
boxShadow: 'inset 0 0 15px rgba(166, 77, 255, 0.2)'
|
||||
}}>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<span className="font-medium" style={{color: 'var(--accent)'}}>{label}</span>
|
||||
<span className="text-sm" style={getTextStyle()}>{percentage}%</span>
|
||||
</div>
|
||||
<div className="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden"
|
||||
style={{boxShadow: '0 2px 5px var(--shadow)'}}>
|
||||
<div
|
||||
className="h-full rounded-full"
|
||||
style={{
|
||||
width: `${percentage}%`,
|
||||
background: 'var(--accent-gradient)',
|
||||
boxShadow: 'inset 0 0 10px rgba(166, 77, 255, 0.5)'
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
<div className="absolute inset-0 rounded-lg pointer-events-none"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.05), rgba(213, 0, 249, 0.05))',
|
||||
border: '1px solid rgba(166, 77, 255, 0.1)',
|
||||
zIndex: 1
|
||||
}}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* DailyHighlights component displays the daily highlights section
|
||||
* including top dream topics and mood categories
|
||||
*/
|
||||
export const DailyHighlights = () => {
|
||||
return (
|
||||
<div className="dreamy-card backdrop-blur-md mb-4"
|
||||
style={{
|
||||
background: 'var(--pink-red-gradient)',
|
||||
animationDelay: '0.3s'
|
||||
}}>
|
||||
<h3 className="font-bold mb-3 dream-title">Tägliche Highlights</h3>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div
|
||||
className="p-4 rounded-lg backdrop-blur-sm transition-all duration-300 hover:transform hover:scale-[1.01]"
|
||||
style={{
|
||||
background: 'var(--purple-gradient)',
|
||||
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.1)',
|
||||
border: '1px solid rgba(166, 77, 255, 0.1)'
|
||||
}}>
|
||||
<h4 className="font-medium mb-3 dream-title text-base">Top Traumthemen</h4>
|
||||
<div className="mb-2">
|
||||
{topDreamTopics.map((topic, index) => (
|
||||
<HighlightCard
|
||||
key={index}
|
||||
label={topic.label}
|
||||
percentage={topic.percentage}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="p-4 rounded-lg backdrop-blur-sm transition-all duration-300 hover:transform hover:scale-[1.01]"
|
||||
style={{
|
||||
background: 'var(--violet-gradient)',
|
||||
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.1)',
|
||||
border: '1px solid rgba(166, 77, 255, 0.1)'
|
||||
}}>
|
||||
<h4 className="font-medium mb-3 dream-title text-base">Stimmungskategorien</h4>
|
||||
<div className="mb-2">
|
||||
{primaryMoodCategories.map((mood, index) => (
|
||||
<HighlightCard
|
||||
key={index}
|
||||
label={mood.label}
|
||||
percentage={mood.percentage}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@@ -3,6 +3,9 @@ import Dream from '../types/Dream';
|
||||
import type User from "../types/User.ts";
|
||||
import {NavLink} from "react-router-dom";
|
||||
import {useEffect, useState} from "react";
|
||||
import {getTextStyle} from '../styles/StyleUtils';
|
||||
import {formatDateWithTime} from '../utils/DateUtils';
|
||||
import {FaMicrochip} from 'react-icons/fa6';
|
||||
|
||||
interface DreamCardProps {
|
||||
dream: Dream;
|
||||
@@ -22,40 +25,55 @@ export default function DreamCard({dream, user, animationDelay = 0}: DreamCardPr
|
||||
}, [animationDelay]);
|
||||
|
||||
return (<NavLink key={dream.id} to={`/dream/${dream.id}`}>
|
||||
<li className={`dream-card card mb-4 transition-all duration-500 ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`}>
|
||||
<div className="flex rounded items-center mb-3">
|
||||
<li className={`dreamy-card backdrop-blur-md mb-4 transition-all duration-500 ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'} relative`}
|
||||
style={{
|
||||
background: 'var(--purple-gradient)',
|
||||
animationDelay: `${animationDelay * 0.2}s`
|
||||
}}>
|
||||
{dream.input.inputType === 'chip' && (
|
||||
<div className="absolute top-6 right-10 w-10 h-10 flex items-center justify-center rounded-full"
|
||||
style={{background: 'var(--accent-gradient)', boxShadow: '0 0 5px var(--shadow)'}}>
|
||||
<FaMicrochip className="w-6 h-6 md:w-8 md:h-8 text-pink-300 opacity-90 hover:opacity-100"/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex rounded items-center mb-4">
|
||||
<div className="relative">
|
||||
<img
|
||||
src={`/assets/profiles/${user?.profilePicture}`}
|
||||
alt={user?.name}
|
||||
className="w-12 h-12 rounded-full border-2 border-accent-soft"
|
||||
style={{borderColor: 'var(--accent-soft)'}}
|
||||
className="w-12 h-12 rounded-full border-2"
|
||||
style={{borderColor: 'var(--accent-soft)', boxShadow: '0 0 10px var(--shadow)'}}
|
||||
/>
|
||||
<div className="absolute -bottom-1 -right-1 w-4 h-4 bg-accent rounded-full"
|
||||
style={{backgroundColor: 'var(--accent)'}}></div>
|
||||
<div className="absolute -bottom-1 -right-1 w-4 h-4 rounded-full"
|
||||
style={{background: 'var(--accent-gradient)'}}></div>
|
||||
</div>
|
||||
<span className="ml-4 font-semibold text-left">{user?.name} <span className="text-text-muted">hat geträumt:</span></span>
|
||||
<span className="ml-4 font-semibold text-left">{user?.name} <span style={getTextStyle('muted')}>hat geträumt:</span></span>
|
||||
</div>
|
||||
<h2 className="title text-left dreamy-text text-lg">
|
||||
{dream.title}
|
||||
</h2>
|
||||
<p className="mt-2 line-clamp-2 text-left">
|
||||
<p className="mt-2 line-clamp-2 text-left" style={getTextStyle()}>
|
||||
{(dream.input.inputType === 'text' && dream.input.input)
|
||||
|| (dream.input.inputType === 'audio' && dream.input.transcript)
|
||||
|| (dream.input.inputType === 'image' && dream.input.description)}
|
||||
|| (dream.input.inputType === 'image' && dream.input.description)
|
||||
|| (dream.input.inputType === 'chip' && dream.input.text)}
|
||||
</p>
|
||||
<div className="flex justify-between items-center mt-3">
|
||||
<p className="timestamp text-left">
|
||||
{dream.date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit',
|
||||
})}
|
||||
<div className="flex justify-between items-center mt-4">
|
||||
<p className="timestamp text-left" style={getTextStyle('muted')}>
|
||||
{formatDateWithTime(dream.date)}
|
||||
</p>
|
||||
<div className="flex space-x-2">
|
||||
{/* Display dream type as a tag */}
|
||||
<span className="px-2 py-1 text-xs rounded-full bg-accent-soft text-text"
|
||||
style={{backgroundColor: 'var(--accent-soft)', color: 'var(--text)'}}>
|
||||
{dream.input.inputType}
|
||||
</span>
|
||||
{/* Display dream tags */}
|
||||
{dream.tags.map((tag, index) => (
|
||||
<span key={index} className="px-2 py-1 text-xs rounded-full"
|
||||
style={{
|
||||
background: 'var(--accent-gradient)',
|
||||
color: 'white',
|
||||
boxShadow: '0 2px 5px var(--shadow)'
|
||||
}}>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
66
src/components/DreamCardCompact.tsx
Normal file
66
src/components/DreamCardCompact.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import {NavLink} from 'react-router-dom';
|
||||
import {formatDateSimple} from '../utils/DateUtils';
|
||||
import Dream from '../types/Dream';
|
||||
import User from '../types/User';
|
||||
import {FaMicrochip} from 'react-icons/fa6';
|
||||
|
||||
interface DreamCardCompactProps {
|
||||
dream: Dream;
|
||||
index: number;
|
||||
showUser?: boolean;
|
||||
user?: User;
|
||||
}
|
||||
|
||||
export const DreamCardCompact = ({dream, index, showUser = false, user}: DreamCardCompactProps) => {
|
||||
return (
|
||||
<NavLink to={`/dream/${dream.id}`}
|
||||
className="block transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] animate-fadeIn rounded-lg mb-4 floating">
|
||||
<div
|
||||
className="p-4 backdrop-blur-sm rounded-lg"
|
||||
style={{
|
||||
animationDelay: `${index * 0.1}s`,
|
||||
background: 'var(--purple-gradient)',
|
||||
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.2)',
|
||||
border: '1px solid rgba(166, 77, 255, 0.1)'
|
||||
}}>
|
||||
{dream.input.inputType === 'chip' && (
|
||||
<div className="absolute bottom-2 right-2 w-10 h-10 flex items-center justify-center rounded-full"
|
||||
style={{background: 'var(--accent-gradient)', boxShadow: '0 0 5px var(--shadow)'}}>
|
||||
<FaMicrochip className="w-6 h-6 md:w-8 md:h-8 text-pink-300 opacity-90 hover:opacity-100"/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col mb-1">
|
||||
{showUser && user && (
|
||||
<div className="flex justify-center mb-2">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className="w-8 h-8 rounded-full mr-2 flex items-center justify-center overflow-hidden border-2"
|
||||
style={{
|
||||
background: 'var(--accent-gradient)',
|
||||
borderColor: 'var(--accent-soft)',
|
||||
boxShadow: '0 2px 5px var(--shadow)'
|
||||
}}>
|
||||
{user.profilePicture ? (
|
||||
<img src={`/assets/profiles/${user.profilePicture}`}
|
||||
alt={user.name} className="w-full h-full object-cover"/>
|
||||
) : (
|
||||
<span
|
||||
className="text-sm text-white">{user.name.charAt(0)}</span>
|
||||
)}
|
||||
</div>
|
||||
<span
|
||||
className="font-medium text-sm dreamy-text">{user.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-center">
|
||||
<h4 className="font-medium dream-title text-xs leading-tight">{dream.title}</h4>
|
||||
<p className="text-xs text-[var(--text-muted)] mt-0.5 opacity-80">
|
||||
{formatDateSimple(dream.date)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
);
|
||||
};
|
350
src/components/DreamCharts.tsx
Normal file
350
src/components/DreamCharts.tsx
Normal file
@@ -0,0 +1,350 @@
|
||||
import React, {useEffect, useRef} from 'react';
|
||||
import * as d3 from 'd3';
|
||||
import type {ChipInput} from '../types/Dream';
|
||||
|
||||
// EEG Chart Component
|
||||
export const EEGChart: React.FC<{ chipInput: ChipInput }> = ({chipInput}) => {
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
const eegData = [
|
||||
{name: 'Alpha', values: chipInput.eeg.alpha},
|
||||
{name: 'Beta', values: chipInput.eeg.beta},
|
||||
{name: 'Theta', values: chipInput.eeg.theta},
|
||||
{name: 'Delta', values: chipInput.eeg.delta}
|
||||
];
|
||||
|
||||
// Function to render the chart
|
||||
const renderChart = () => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
// Clear previous chart
|
||||
d3.select(chartRef.current).selectAll('*').remove();
|
||||
|
||||
const margin = {top: 20, right: 20, bottom: 30, left: 50};
|
||||
const width = chartRef.current.clientWidth - margin.left - margin.right;
|
||||
const height = chartRef.current.clientHeight - margin.top - margin.bottom;
|
||||
|
||||
const svg = d3.select(chartRef.current)
|
||||
.append('svg')
|
||||
.attr('width', width + margin.left + margin.right)
|
||||
.attr('height', height + margin.top + margin.bottom)
|
||||
.append('g')
|
||||
.attr('transform', `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// X scale
|
||||
const x = d3.scaleLinear()
|
||||
.domain([0, chipInput.eeg.alpha.length - 1])
|
||||
.range([0, width]);
|
||||
|
||||
// Y scale
|
||||
const y = d3.scaleLinear()
|
||||
.domain([0, d3.max(eegData.flatMap(d => d.values)) || 50])
|
||||
.range([height, 0]);
|
||||
|
||||
// Line generator
|
||||
const line = d3.line<number>()
|
||||
.x((_d, i) => x(i))
|
||||
.y(d => y(d))
|
||||
.curve(d3.curveMonotoneX);
|
||||
|
||||
// Color scale
|
||||
const color = d3.scaleOrdinal<string>()
|
||||
.domain(eegData.map(d => d.name))
|
||||
.range(['#8884d8', '#82ca9d', '#ffc658', '#ff8042']);
|
||||
|
||||
// Add X axis
|
||||
svg.append('g')
|
||||
.attr('transform', `translate(0,${height})`)
|
||||
.call(d3.axisBottom(x))
|
||||
.selectAll('text')
|
||||
.style('fill', 'var(--text)');
|
||||
|
||||
// Add Y axis
|
||||
svg.append('g')
|
||||
.call(d3.axisLeft(y))
|
||||
.selectAll('text')
|
||||
.style('fill', 'var(--text)');
|
||||
|
||||
// Add lines
|
||||
eegData.forEach(d => {
|
||||
svg.append('path')
|
||||
.datum(d.values)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', color(d.name))
|
||||
.attr('stroke-width', 1.5)
|
||||
.attr('d', line);
|
||||
});
|
||||
|
||||
// Add legend at the top right
|
||||
const legendItemHeight = 20; // Height allocated for each legend item
|
||||
|
||||
const legend = svg.append('g')
|
||||
.attr('font-family', 'sans-serif')
|
||||
.attr('font-size', 10)
|
||||
.attr('text-anchor', 'end')
|
||||
.selectAll('g')
|
||||
.data(eegData)
|
||||
.enter().append('g')
|
||||
.attr('transform', (_d, i) => `translate(${width},${i * legendItemHeight + 10})`);
|
||||
|
||||
legend.append('rect')
|
||||
.attr('x', -15)
|
||||
.attr('width', 15)
|
||||
.attr('height', 15)
|
||||
.attr('fill', d => color(d.name));
|
||||
|
||||
legend.append('text')
|
||||
.attr('x', -20)
|
||||
.attr('y', 7.5)
|
||||
.attr('dy', '0.32em')
|
||||
.style('fill', 'var(--text)')
|
||||
.text(d => d.name);
|
||||
};
|
||||
|
||||
// Initial render
|
||||
renderChart();
|
||||
|
||||
// Handle resize
|
||||
const handleResize = () => {
|
||||
if (!chartRef.current) return;
|
||||
renderChart();
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [chipInput]);
|
||||
|
||||
return <div ref={chartRef} className="w-full h-64 border border-gray-200 rounded-lg p-2"></div>;
|
||||
};
|
||||
|
||||
// Vitals Chart Component
|
||||
export const VitalsChart: React.FC<{ chipInput: ChipInput }> = ({chipInput}) => {
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
const vitalsData = [
|
||||
{name: 'Puls', values: chipInput.puls},
|
||||
{name: 'HRV', values: chipInput.hrv}
|
||||
];
|
||||
|
||||
// Function to render the chart
|
||||
const renderChart = () => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
// Clear previous chart
|
||||
d3.select(chartRef.current).selectAll('*').remove();
|
||||
|
||||
const margin = {top: 20, right: 20, bottom: 30, left: 50};
|
||||
const width = chartRef.current.clientWidth - margin.left - margin.right;
|
||||
const height = chartRef.current.clientHeight - margin.top - margin.bottom;
|
||||
|
||||
const svg = d3.select(chartRef.current)
|
||||
.append('svg')
|
||||
.attr('width', width + margin.left + margin.right)
|
||||
.attr('height', height + margin.top + margin.bottom)
|
||||
.append('g')
|
||||
.attr('transform', `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// X scale
|
||||
const x = d3.scaleLinear()
|
||||
.domain([0, chipInput.puls.length - 1])
|
||||
.range([0, width]);
|
||||
|
||||
// Y scale
|
||||
const minValue = d3.min(vitalsData.flatMap(d => d.values)) || 0;
|
||||
const maxValue = d3.max(vitalsData.flatMap(d => d.values)) || 100;
|
||||
const y = d3.scaleLinear()
|
||||
.domain([Math.max(0, minValue - 10), maxValue + 10])
|
||||
.range([height, 0]);
|
||||
|
||||
// Line generator
|
||||
const line = d3.line<number>()
|
||||
.x((_d, i) => x(i))
|
||||
.y(d => y(d))
|
||||
.curve(d3.curveMonotoneX);
|
||||
|
||||
// Color scale
|
||||
const color = d3.scaleOrdinal<string>()
|
||||
.domain(vitalsData.map(d => d.name))
|
||||
.range(['#ff6b6b', '#48dbfb']);
|
||||
|
||||
// Add X axis
|
||||
svg.append('g')
|
||||
.attr('transform', `translate(0,${height})`)
|
||||
.call(d3.axisBottom(x))
|
||||
.selectAll('text')
|
||||
.style('fill', 'var(--text)');
|
||||
|
||||
// Add Y axis
|
||||
svg.append('g')
|
||||
.call(d3.axisLeft(y))
|
||||
.selectAll('text')
|
||||
.style('fill', 'var(--text)');
|
||||
|
||||
// Add lines
|
||||
vitalsData.forEach(d => {
|
||||
svg.append('path')
|
||||
.datum(d.values)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', color(d.name))
|
||||
.attr('stroke-width', 1.5)
|
||||
.attr('d', line);
|
||||
});
|
||||
|
||||
// Add legend at the top right
|
||||
const legendItemHeight = 20; // Height allocated for each legend item
|
||||
|
||||
const legend = svg.append('g')
|
||||
.attr('font-family', 'sans-serif')
|
||||
.attr('font-size', 10)
|
||||
.attr('text-anchor', 'end')
|
||||
.selectAll('g')
|
||||
.data(vitalsData)
|
||||
.enter().append('g')
|
||||
.attr('transform', (_d, i) => `translate(${width},${i * legendItemHeight + 10})`);
|
||||
|
||||
legend.append('rect')
|
||||
.attr('x', -15)
|
||||
.attr('width', 15)
|
||||
.attr('height', 15)
|
||||
.attr('fill', d => color(d.name));
|
||||
|
||||
legend.append('text')
|
||||
.attr('x', -20)
|
||||
.attr('y', 7.5)
|
||||
.attr('dy', '0.32em')
|
||||
.style('fill', 'var(--text)')
|
||||
.text(d => d.name);
|
||||
};
|
||||
|
||||
// Initial render
|
||||
renderChart();
|
||||
|
||||
// Handle resize
|
||||
const handleResize = () => {
|
||||
if (!chartRef.current) return;
|
||||
renderChart();
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [chipInput]);
|
||||
|
||||
return <div ref={chartRef} className="w-full h-64 border border-gray-200 rounded-lg p-2"></div>;
|
||||
};
|
||||
|
||||
// Movement Chart Component
|
||||
export const MovementChart: React.FC<{ chipInput: ChipInput }> = ({chipInput}) => {
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
const bewegungData = [
|
||||
{name: 'Bewegung', values: chipInput.bewegung.map(v => v * 100)} // Scale movement for better visibility
|
||||
];
|
||||
|
||||
// Function to render the chart
|
||||
const renderChart = () => {
|
||||
if (!chartRef.current) return;
|
||||
|
||||
// Clear previous chart
|
||||
d3.select(chartRef.current).selectAll('*').remove();
|
||||
|
||||
const margin = {top: 20, right: 20, bottom: 30, left: 50};
|
||||
const width = chartRef.current.clientWidth - margin.left - margin.right;
|
||||
const height = chartRef.current.clientHeight - margin.top - margin.bottom;
|
||||
|
||||
const svg = d3.select(chartRef.current)
|
||||
.append('svg')
|
||||
.attr('width', width + margin.left + margin.right)
|
||||
.attr('height', height + margin.top + margin.bottom)
|
||||
.append('g')
|
||||
.attr('transform', `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// X scale
|
||||
const x = d3.scaleLinear()
|
||||
.domain([0, chipInput.bewegung.length - 1])
|
||||
.range([0, width]);
|
||||
|
||||
// Y scale
|
||||
const y = d3.scaleLinear()
|
||||
.domain([0, d3.max(bewegungData[0].values) || 100])
|
||||
.range([height, 0]);
|
||||
|
||||
// Line generator
|
||||
const line = d3.line<number>()
|
||||
.x((_d, i) => x(i))
|
||||
.y(d => y(d))
|
||||
.curve(d3.curveMonotoneX);
|
||||
|
||||
// Color scale
|
||||
const color = '#1dd1a1'; // Use the same color as before for consistency
|
||||
|
||||
// Add X axis
|
||||
svg.append('g')
|
||||
.attr('transform', `translate(0,${height})`)
|
||||
.call(d3.axisBottom(x))
|
||||
.selectAll('text')
|
||||
.style('fill', 'var(--text)');
|
||||
|
||||
// Add Y axis
|
||||
svg.append('g')
|
||||
.call(d3.axisLeft(y))
|
||||
.selectAll('text')
|
||||
.style('fill', 'var(--text)');
|
||||
|
||||
// Add line
|
||||
svg.append('path')
|
||||
.datum(bewegungData[0].values)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', color)
|
||||
.attr('stroke-width', 1.5)
|
||||
.attr('d', line);
|
||||
|
||||
// Add legend at the top right
|
||||
const legendItemHeight = 20; // Height allocated for each legend item
|
||||
|
||||
const legend = svg.append('g')
|
||||
.attr('font-family', 'sans-serif')
|
||||
.attr('font-size', 10)
|
||||
.attr('text-anchor', 'end')
|
||||
.selectAll('g')
|
||||
.data(bewegungData)
|
||||
.enter().append('g')
|
||||
.attr('transform', (_d, i) => `translate(${width},${i * legendItemHeight + 10})`);
|
||||
|
||||
legend.append('rect')
|
||||
.attr('x', -15)
|
||||
.attr('width', 15)
|
||||
.attr('height', 15)
|
||||
.attr('fill', () => color);
|
||||
|
||||
legend.append('text')
|
||||
.attr('x', -20)
|
||||
.attr('y', 7.5)
|
||||
.attr('dy', '0.32em')
|
||||
.style('fill', 'var(--text)')
|
||||
.text(d => d.name);
|
||||
};
|
||||
|
||||
// Initial render
|
||||
renderChart();
|
||||
|
||||
// Handle resize
|
||||
const handleResize = () => {
|
||||
if (!chartRef.current) return;
|
||||
renderChart();
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [chipInput]);
|
||||
|
||||
return <div ref={chartRef} className="w-full h-64 border border-gray-200 rounded-lg p-2"></div>;
|
||||
};
|
78
src/components/DreamRecord.tsx
Normal file
78
src/components/DreamRecord.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import {useState} from "react";
|
||||
import {getAccentStyle, getBackgroundStyle, getCardStyle, getTextStyle} from "../styles/StyleUtils.ts";
|
||||
|
||||
export function DreamRecord() {
|
||||
const [inputMode, setInputMode] = useState<'text' | 'drawing'>('text');
|
||||
|
||||
return (
|
||||
<div className={getCardStyle().className}
|
||||
style={getCardStyle()}>
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h3 className="font-bold dream-title">Neuer Traum</h3>
|
||||
<div className="flex rounded-lg overflow-hidden" style={{border: '1px solid var(--accent-soft)'}}>
|
||||
<button
|
||||
className={`px-3 py-1 text-sm transition-all duration-200`}
|
||||
onClick={() => setInputMode('text')}
|
||||
style={getAccentStyle(false, inputMode === 'text')}
|
||||
>
|
||||
Text
|
||||
</button>
|
||||
<button
|
||||
className={`px-3 py-1 text-sm transition-all duration-200`}
|
||||
onClick={() => setInputMode('drawing')}
|
||||
style={getAccentStyle(false, inputMode === 'drawing')}
|
||||
>
|
||||
Zeichnung
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{inputMode === 'text' ? (
|
||||
<textarea
|
||||
className="w-full p-4 rounded-lg mb-4 transition-all duration-200"
|
||||
rows={4}
|
||||
placeholder="Beschreibe deinen Traum..."
|
||||
style={{
|
||||
...getBackgroundStyle('normal'),
|
||||
...getTextStyle(),
|
||||
border: '1px solid var(--accent-soft)'
|
||||
}}
|
||||
></textarea>
|
||||
) : (
|
||||
<div
|
||||
className="w-full h-40 rounded-lg mb-4 flex items-center justify-center border-2 border-dashed transition-all duration-200"
|
||||
style={{
|
||||
...getBackgroundStyle('normal'),
|
||||
borderColor: 'var(--accent-soft)'
|
||||
}}>
|
||||
<p style={getTextStyle('muted')}>Zeichne deinen Traum hier (Canvas-Platzhalter)</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between">
|
||||
<div className="flex space-x-2">
|
||||
<button className="p-2 rounded-full transition-all duration-200 hover:transform hover:scale-110"
|
||||
style={getAccentStyle(true)}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button className="p-2 rounded-full transition-all duration-200 hover:transform hover:scale-110"
|
||||
style={getAccentStyle(true)}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<button className="px-4 py-2 rounded-lg transition-all duration-200 hover:transform hover:scale-105"
|
||||
style={getBackgroundStyle('accent-gradient')}>
|
||||
Senden
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
249
src/components/DreamVR.tsx
Normal file
249
src/components/DreamVR.tsx
Normal file
@@ -0,0 +1,249 @@
|
||||
import React, {useMemo, useRef} from 'react';
|
||||
import {Canvas, useFrame} from '@react-three/fiber';
|
||||
import {createXRStore, useXR, XR} from '@react-three/xr';
|
||||
import {OrbitControls, PerspectiveCamera} from '@react-three/drei';
|
||||
import * as THREE from 'three';
|
||||
import type Dream from '../types/Dream';
|
||||
|
||||
// Neural Node component representing a synapse in the neural network
|
||||
const NeuralNode = ({position, color, scale, pulseSpeed, pulseIntensity}: {
|
||||
position: [number, number, number], color: string, scale: number, pulseSpeed: number, pulseIntensity: number
|
||||
}) => {
|
||||
const nodeRef = useRef<THREE.Mesh>(null);
|
||||
const initialScale = scale;
|
||||
|
||||
useFrame(({clock}) => {
|
||||
if (nodeRef.current) {
|
||||
// Create a pulsing effect
|
||||
const pulse = Math.sin(clock.getElapsedTime() * pulseSpeed) * pulseIntensity + 1;
|
||||
nodeRef.current.scale.set(initialScale * pulse, initialScale * pulse, initialScale * pulse);
|
||||
}
|
||||
});
|
||||
|
||||
return (<mesh ref={nodeRef} position={position}>
|
||||
<sphereGeometry args={[scale, 8, 8]}/>
|
||||
<meshStandardMaterial color={color} emissive={color} emissiveIntensity={0.2}/>
|
||||
</mesh>);
|
||||
};
|
||||
|
||||
// Neural Connection component representing connections between synapses
|
||||
const NeuralConnection = ({start, end, color, thickness, pulseSpeed, pulseIntensity}: {
|
||||
start: [number, number, number],
|
||||
end: [number, number, number],
|
||||
color: string,
|
||||
thickness: number,
|
||||
pulseSpeed: number,
|
||||
pulseIntensity: number
|
||||
}) => {
|
||||
const connectionRef = useRef<THREE.Mesh>(null);
|
||||
|
||||
// Create a cylinder between two points
|
||||
const direction = useMemo(() => {
|
||||
return new THREE.Vector3(end[0] - start[0], end[1] - start[1], end[2] - start[2]);
|
||||
}, [start, end]);
|
||||
|
||||
const length = useMemo(() => direction.length(), [direction]);
|
||||
|
||||
// Calculate rotation to align cylinder with direction
|
||||
useMemo(() => {
|
||||
const normalizedDirection = direction.clone().normalize();
|
||||
const quaternion = new THREE.Quaternion();
|
||||
quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), // Default cylinder orientation
|
||||
normalizedDirection);
|
||||
return new THREE.Matrix4().makeRotationFromQuaternion(quaternion);
|
||||
}, [direction]);
|
||||
// Calculate position (midpoint between start and end)
|
||||
const position = useMemo(() => {
|
||||
return [(start[0] + end[0]) / 2, (start[1] + end[1]) / 2, (start[2] + end[2]) / 2] as [number, number, number];
|
||||
}, [start, end]);
|
||||
|
||||
useFrame(({clock}) => {
|
||||
if (connectionRef.current) {
|
||||
// Create a pulsing effect for the connection
|
||||
const pulse = Math.sin(clock.getElapsedTime() * pulseSpeed + (start[0] + start[1] + start[2])) * pulseIntensity + 1;
|
||||
connectionRef.current.scale.set(thickness * pulse, length / 2, thickness * pulse);
|
||||
}
|
||||
});
|
||||
|
||||
return (<mesh ref={connectionRef} position={position}>
|
||||
<cylinderGeometry args={[thickness, thickness, length]}/>
|
||||
<meshStandardMaterial color={color} emissive={color} emissiveIntensity={0.1}/>
|
||||
</mesh>);
|
||||
};
|
||||
|
||||
// Neural Network component that generates nodes and connections
|
||||
const NeuralNetwork = ({dream}: { dream: Dream }) => {
|
||||
// Generate nodes and connections based on dream data
|
||||
const nodes = useMemo(() => {
|
||||
if (dream.input.inputType !== 'chip') return [];
|
||||
|
||||
const chipInput = dream.input;
|
||||
const nodeCount = 50; // Number of nodes to generate
|
||||
const nodes = [];
|
||||
|
||||
// Use EEG data to influence node positions and properties
|
||||
for (let i = 0; i < nodeCount; i++) {
|
||||
const alphaValue = chipInput.eeg.alpha[i % chipInput.eeg.alpha.length] / 50;
|
||||
const betaValue = chipInput.eeg.beta[i % chipInput.eeg.beta.length] / 50;
|
||||
const thetaValue = chipInput.eeg.theta[i % chipInput.eeg.theta.length] / 50;
|
||||
|
||||
// Calculate position based on EEG values
|
||||
const x = (Math.random() - 0.5) * 20 + alphaValue * 10;
|
||||
const y = (Math.random() - 0.5) * 20 + betaValue * 10;
|
||||
const z = (Math.random() - 0.5) * 20 + thetaValue * 10;
|
||||
|
||||
// Determine color based on dominant wave
|
||||
let color;
|
||||
const dominantWave = Math.max(alphaValue, betaValue, thetaValue);
|
||||
if (dominantWave === alphaValue) {
|
||||
color = '#8884d8'; // Alpha - purple
|
||||
} else if (dominantWave === betaValue) {
|
||||
color = '#82ca9d'; // Beta - green
|
||||
} else {
|
||||
color = '#ffc658'; // Theta - yellow
|
||||
}
|
||||
|
||||
// Scale based on pulse data
|
||||
const scale = 0.2 + (chipInput.puls[i % chipInput.puls.length] / 200);
|
||||
|
||||
// Pulse speed and intensity based on HRV and movement
|
||||
const pulseSpeed = 1 + (chipInput.hrv[i % chipInput.hrv.length] / 35);
|
||||
const pulseIntensity = 0.1 + (chipInput.bewegung[i % chipInput.bewegung.length] * 2);
|
||||
|
||||
nodes.push({
|
||||
position: [x, y, z] as [number, number, number], color, scale, pulseSpeed, pulseIntensity
|
||||
});
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}, [dream]);
|
||||
|
||||
// Generate connections between nodes
|
||||
const connections = useMemo(() => {
|
||||
if (dream.input.inputType !== 'chip') return [];
|
||||
|
||||
const connections = [];
|
||||
const connectionCount = nodes.length * 2; // Each node connects to ~2 others
|
||||
|
||||
for (let i = 0; i < connectionCount; i++) {
|
||||
const startNodeIndex = i % nodes.length;
|
||||
// Connect to a nearby node (not completely random)
|
||||
const endNodeIndex = (startNodeIndex + 1 + Math.floor(Math.random() * 5)) % nodes.length;
|
||||
|
||||
if (startNodeIndex !== endNodeIndex) {
|
||||
connections.push({
|
||||
start: nodes[startNodeIndex].position,
|
||||
end: nodes[endNodeIndex].position,
|
||||
color: nodes[startNodeIndex].color,
|
||||
thickness: 0.05 + Math.random() * 0.05,
|
||||
pulseSpeed: nodes[startNodeIndex].pulseSpeed,
|
||||
pulseIntensity: nodes[startNodeIndex].pulseIntensity
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return connections;
|
||||
}, [nodes, dream]);
|
||||
|
||||
return (<>
|
||||
{/* Render all nodes */}
|
||||
{nodes.map((node, index) => (<NeuralNode
|
||||
key={index}
|
||||
position={node.position}
|
||||
color={node.color}
|
||||
scale={node.scale}
|
||||
pulseSpeed={node.pulseSpeed}
|
||||
pulseIntensity={node.pulseIntensity}
|
||||
/>))}
|
||||
|
||||
{/* Render all connections */}
|
||||
{connections.map((connection, index) => (<NeuralConnection
|
||||
key={index}
|
||||
start={connection.start}
|
||||
end={connection.end}
|
||||
color={connection.color}
|
||||
thickness={connection.thickness}
|
||||
pulseSpeed={connection.pulseSpeed}
|
||||
pulseIntensity={connection.pulseIntensity}
|
||||
/>))}
|
||||
</>);
|
||||
};
|
||||
|
||||
// Camera Controls component that handles XR and non-XR states
|
||||
const CameraControls = () => {
|
||||
const {session} = useXR();
|
||||
|
||||
// Only enable OrbitControls when NOT in VR session
|
||||
if (session) {
|
||||
return null; // Let XR handle camera in VR mode
|
||||
}
|
||||
|
||||
return (<OrbitControls
|
||||
enablePan={true}
|
||||
enableZoom={true}
|
||||
enableRotate={true}
|
||||
enableDamping={true}
|
||||
dampingFactor={0.05}
|
||||
minDistance={5}
|
||||
maxDistance={50}
|
||||
maxPolarAngle={Math.PI}
|
||||
minPolarAngle={0}
|
||||
/>);
|
||||
};
|
||||
|
||||
// Main DreamVR component
|
||||
interface DreamVRProps {
|
||||
dream: Dream;
|
||||
height?: string;
|
||||
}
|
||||
|
||||
// Create XR store outside the component to avoid recreation on each render
|
||||
const store = createXRStore();
|
||||
|
||||
const DreamVR: React.FC<DreamVRProps> = ({dream, height = '500px'}) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Only render VR for dream with chip input type
|
||||
if (dream.input.inputType !== 'chip') {
|
||||
return (<div className="flex items-center justify-center h-full text-gray-500">
|
||||
VR-Visualisierung ist nur für Träume mit Chip-Eingabe verfügbar.
|
||||
</div>);
|
||||
}
|
||||
|
||||
return (<div ref={containerRef} className="relative w-full" style={{height}}>
|
||||
{/* VR Entry Button */}
|
||||
<button
|
||||
onClick={() => store.enterVR()}
|
||||
className="absolute top-4 right-4 z-10 p-2 bg-white/20 backdrop-blur-sm rounded-full text-white hover:bg-white/30 transition-colors"
|
||||
aria-label="Enter VR"
|
||||
>
|
||||
🥽 VR
|
||||
</button>
|
||||
|
||||
<Canvas camera={{position: [0, 0, 10], fov: 60}}>
|
||||
<XR store={store}>
|
||||
{/* Camera setup */}
|
||||
<PerspectiveCamera makeDefault position={[0, 0, 10]}/>
|
||||
|
||||
{/* Camera Controls - only active outside VR */}
|
||||
<CameraControls/>
|
||||
|
||||
{/* Lighting */}
|
||||
<ambientLight intensity={0.2}/>
|
||||
<pointLight position={[10, 10, 10]} intensity={0.8}/>
|
||||
<pointLight position={[-10, -10, -10]} intensity={0.4}/>
|
||||
|
||||
{/* Neural network visualization */}
|
||||
<NeuralNetwork dream={dream}/>
|
||||
|
||||
{/* Background */}
|
||||
<mesh scale={[100, 100, 100]}>
|
||||
<sphereGeometry args={[1, 32, 32]}/>
|
||||
<meshBasicMaterial color="#000012" side={THREE.BackSide}/>
|
||||
</mesh>
|
||||
</XR>
|
||||
</Canvas>
|
||||
</div>);
|
||||
};
|
||||
|
||||
export default DreamVR;
|
@@ -1,30 +1,35 @@
|
||||
import {NavLink} from 'react-router-dom';
|
||||
import {FaArchive, FaHome, FaList, FaMicrophone, FaUser} from "react-icons/fa";
|
||||
import {FaMicrochip, FaMicrophone, FaUser} from "react-icons/fa6";
|
||||
import {FaGlobeEurope, FaHome} from "react-icons/fa";
|
||||
import {getBackgroundStyle} from '../styles/StyleUtils';
|
||||
|
||||
export default function Navbar() {
|
||||
return (<>
|
||||
<nav
|
||||
className="fixed bottom-0 left-0 right-0 flex justify-around py-4 z-10"
|
||||
style={{backgroundColor: 'var(--accent-dark)', boxShadow: '0 -2px 10px var(--shadow)'}}>
|
||||
className="fixed bottom-0 left-0 right-0 flex justify-around py-4 z-50 backdrop-blur-md"
|
||||
style={{
|
||||
background: 'var(--accent-gradient)',
|
||||
boxShadow: '0 -2px 10px var(--shadow)'
|
||||
}}>
|
||||
<NavLink to="/home" className="transition-transform hover:scale-110">
|
||||
<FaHome className="w-6 h-6 md:w-8 md:h-8" style={{color: 'var(--accent-soft)'}}/>
|
||||
<FaHome className="w-6 h-6 md:w-8 md:h-8 text-white opacity-90 hover:opacity-100"/>
|
||||
</NavLink>
|
||||
<NavLink to="/feed" className="transition-transform hover:scale-110">
|
||||
<FaList className="w-6 h-6 md:w-8 md:h-8" style={{color: 'var(--accent-soft)'}}/>
|
||||
<NavLink to="/chip" className="transition-transform hover:scale-110">
|
||||
<FaMicrochip className="w-6 h-6 md:w-8 md:h-8 text-white opacity-90 hover:opacity-100"/>
|
||||
</NavLink>
|
||||
<div className="w-16 md:w-20"></div>
|
||||
<NavLink to="/archive" className="transition-transform hover:scale-110">
|
||||
<FaArchive className="w-6 h-6 md:w-8 md:h-8" style={{color: 'var(--accent-soft)'}}/>
|
||||
<NavLink to="/dreamarchive" className="transition-transform hover:scale-110">
|
||||
<FaGlobeEurope className="w-6 h-6 md:w-8 md:h-8 text-white opacity-90 hover:opacity-100"/>
|
||||
</NavLink>
|
||||
<NavLink to="/profile" className="transition-transform hover:scale-110">
|
||||
<FaUser className="w-6 h-6 md:w-8 md:h-8" style={{color: 'var(--accent-soft)'}}/>
|
||||
<FaUser className="w-6 h-6 md:w-8 md:h-8 text-white opacity-90 hover:opacity-100"/>
|
||||
</NavLink>
|
||||
</nav>
|
||||
|
||||
<NavLink
|
||||
to="/record"
|
||||
className="microphone-button fixed bottom-6 left-1/2 transform -translate-x-1/2 p-4 md:p-5 rounded-full z-20 transition-transform hover:scale-110"
|
||||
style={{boxShadow: '0 4px 15px var(--shadow)'}}
|
||||
className="microphone-button fixed bottom-6 left-1/2 transform -translate-x-1/2 p-4 md:p-5 rounded-full z-60 transition-transform hover:scale-110 floating"
|
||||
style={getBackgroundStyle('cta')}
|
||||
>
|
||||
<FaMicrophone className="w-8 h-8 md:w-10 md:h-10 text-white"/>
|
||||
</NavLink>
|
||||
|
15
src/components/ScrollToTop.tsx
Normal file
15
src/components/ScrollToTop.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
// src/components/ScrollToTop.tsx
|
||||
import {useEffect} from 'react';
|
||||
import {useLocation} from 'react-router-dom';
|
||||
|
||||
const ScrollToTop: React.FC = () => {
|
||||
const {pathname} = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0);
|
||||
}, [pathname]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default ScrollToTop;
|
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from 'react';
|
||||
import {useEffect} from 'react';
|
||||
import logo from '../assets/logo.svg';
|
||||
import text from '../assets/text.svg';
|
||||
|
||||
@@ -17,15 +17,22 @@ export default function SplashScreen({ onFinished }: SplashScreenProps) {
|
||||
}, [onFinished]);
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 flex flex-col items-center justify-center z-50 bg-gradient-to-br from-fuchsia-900 via-pink-700 to-purple-900">
|
||||
<div className="fixed inset-0 flex flex-col items-center justify-center z-50" style={{
|
||||
background: 'linear-gradient(135deg, #2e0854, #4a0e8f, #6a0dad, #8a2be2)',
|
||||
backgroundSize: '400% 400%',
|
||||
animation: 'gradient-animation 15s ease infinite'
|
||||
}}>
|
||||
<div className="animate-pulse flex flex-col items-center">
|
||||
<img src={logo} alt="REMind Logo" className="h-32 w-32 mb-4" />
|
||||
<img src={text} alt="REMind Text" className="h-16" />
|
||||
</div>
|
||||
<div className="mt-8 text-fuchsia-400">
|
||||
<div className="animate-spin h-8 w-8 border-4 border-current border-t-transparent rounded-full mx-auto"></div>
|
||||
<div className="mt-8" style={{color: 'var(--text)'}}>
|
||||
<div className="animate-spin h-8 w-8 border-4 rounded-full mx-auto" style={{
|
||||
borderColor: 'var(--text)',
|
||||
borderTopColor: 'transparent'
|
||||
}}></div>
|
||||
<p className="mt-4 text-center">Loading your dreams...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import {useEffect, useState} from 'react';
|
||||
import logotext from "../assets/logotext.svg";
|
||||
import {NavLink} from "react-router-dom";
|
||||
import {getBackgroundStyle} from '../styles/StyleUtils';
|
||||
|
||||
export default function TopBar() {
|
||||
const [visible, setVisible] = useState(true);
|
||||
@@ -56,9 +57,7 @@ export default function TopBar() {
|
||||
|
||||
return (<div
|
||||
className={`fixed top-0 left-0 right-0 py-2 md:py-3 px-3 md:px-4 flex items-center transition-transform duration-300 z-20 ${visible ? 'transform-none' : 'transform -translate-y-full'}`}
|
||||
style={{
|
||||
background: 'var(--accent-gradient)', boxShadow: '0 2px 10px var(--shadow)'
|
||||
}}
|
||||
style={getBackgroundStyle('topbar')}
|
||||
>
|
||||
<div className="flex items-center justify-between w-full max-w-6xl mx-auto">
|
||||
<div className="flex items-center">
|
||||
@@ -72,18 +71,21 @@ export default function TopBar() {
|
||||
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="p-2 rounded-full focus:outline-none transition-transform hover:scale-110"
|
||||
className="p-2 rounded-full focus:outline-none transition-transform hover:scale-110 floating"
|
||||
aria-label="Toggle theme"
|
||||
style={{
|
||||
backgroundColor: 'var(--card)', boxShadow: '0 2px 8px var(--shadow)'
|
||||
background: 'rgba(255, 255, 255, 0.2)',
|
||||
backdropFilter: 'blur(10px)',
|
||||
boxShadow: '0 4px 10px rgba(0, 0, 0, 0.2)',
|
||||
animationDelay: '0.5s'
|
||||
}}
|
||||
>
|
||||
{darkMode ? (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 md:h-6 md:w-6" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor" style={{color: 'var(--accent)'}}>
|
||||
viewBox="0 0 24 24" stroke="white">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/>
|
||||
</svg>) : (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 md:h-6 md:w-6" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor" style={{color: 'var(--accent-dark)'}}>
|
||||
viewBox="0 0 24 24" stroke="white">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/>
|
||||
</svg>)}
|
||||
|
28
src/components/dreamarchive/DreamyCard.tsx
Normal file
28
src/components/dreamarchive/DreamyCard.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import type {ReactNode} from 'react';
|
||||
import React from 'react';
|
||||
import {getBackgroundStyle} from '../../styles/StyleUtils';
|
||||
|
||||
interface DreamyCardProps {
|
||||
children: ReactNode;
|
||||
color?: 'purple' | 'blue' | 'violet' | 'emerald' | 'amber' | 'rose' | 'pink-red' | 'cta';
|
||||
className?: string;
|
||||
padding?: string;
|
||||
}
|
||||
|
||||
export const DreamyCard: React.FC<DreamyCardProps> = ({
|
||||
children,
|
||||
color = 'purple',
|
||||
className = '',
|
||||
padding = 'p-6'
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={`dreamy-card ${padding} ${className}`}
|
||||
style={getBackgroundStyle(color)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DreamyCard;
|
27
src/components/dreamarchive/HeroSection.tsx
Normal file
27
src/components/dreamarchive/HeroSection.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
|
||||
interface HeroSectionProps {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
containerTitle: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const HeroSection: React.FC<HeroSectionProps> = ({containerTitle, description}) => {
|
||||
return (
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div
|
||||
className="dream-container floating max-w-3xl mx-auto backdrop-blur-sm bg-white/10 dark:bg-white/5 rounded-3xl p-4 sm:p-6 md:p-8"
|
||||
style={{animationDelay: '0.2s'}}>
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-3 sm:mb-4">
|
||||
<h2 className="dream-title text-xl sm:text-2xl">{containerTitle}</h2>
|
||||
</div>
|
||||
<p className="mb-4 sm:mb-6 md:mb-8 text-sm sm:text-base md:text-lg" style={{color: 'var(--text)'}}>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroSection;
|
27
src/components/dreamarchive/IconWithBackground.tsx
Normal file
27
src/components/dreamarchive/IconWithBackground.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import type {ReactElement} from 'react';
|
||||
import React from 'react';
|
||||
|
||||
interface IconWithBackgroundProps {
|
||||
icon: ReactElement;
|
||||
color: string;
|
||||
size?: number;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const IconWithBackground: React.FC<IconWithBackgroundProps> = ({
|
||||
icon,
|
||||
color,
|
||||
size = 28,
|
||||
className = ''
|
||||
}) => {
|
||||
return (
|
||||
<div className={`p-3 bg-${color}-500/20 rounded-full ${className}`}>
|
||||
{React.cloneElement(icon, {
|
||||
className: `text-${color}-600 dark:text-${color}-400`,
|
||||
size: size
|
||||
} as React.SVGProps<SVGSVGElement>)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default IconWithBackground;
|
48
src/components/dreamarchive/ResearcherInterviewCard.tsx
Normal file
48
src/components/dreamarchive/ResearcherInterviewCard.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import {FaUserMd} from 'react-icons/fa';
|
||||
import {getBackgroundStyle, getTextStyle} from '../../styles/StyleUtils';
|
||||
import IconWithBackground from './IconWithBackground';
|
||||
import VideoPlayer from './VideoPlayer';
|
||||
|
||||
interface ResearcherInterviewCardProps {
|
||||
interview: {
|
||||
id: number;
|
||||
name: string;
|
||||
institution: string;
|
||||
specialty: string;
|
||||
topics: string[];
|
||||
color: 'purple' | 'blue' | 'violet' | 'emerald' | 'amber' | 'rose' | 'pink-red' | 'cta';
|
||||
videoId: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const ResearcherInterviewCard: React.FC<ResearcherInterviewCardProps> = ({interview}) => {
|
||||
return (
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle(interview.color)}>
|
||||
<div className="flex items-start mb-4">
|
||||
<IconWithBackground
|
||||
icon={<FaUserMd/>}
|
||||
color={interview.color}
|
||||
size={28}
|
||||
className="mr-4 mt-1"
|
||||
/>
|
||||
<div>
|
||||
<h3 className="text-lg font-bold dreamy-text">{interview.name}</h3>
|
||||
<p className="text-xs mb-1" style={getTextStyle('muted')}>{interview.institution}</p>
|
||||
<p className="text-sm mb-3">{interview.specialty}</p>
|
||||
|
||||
<VideoPlayer color={interview.color}/>
|
||||
|
||||
<h4 className="font-bold mt-3 mb-1">Themen im Interview:</h4>
|
||||
<ul className="list-disc list-inside text-sm space-y-1">
|
||||
{interview.topics.map((topic, index) => (
|
||||
<li key={index}>{topic}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResearcherInterviewCard;
|
14
src/components/dreamarchive/SectionHeader.tsx
Normal file
14
src/components/dreamarchive/SectionHeader.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
interface SectionHeaderProps {
|
||||
title: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const SectionHeader: React.FC<SectionHeaderProps> = ({title, className = ''}) => {
|
||||
return (
|
||||
<h2 className={`text-2xl font-bold mb-6 dream-title ${className}`}>{title}</h2>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionHeader;
|
73
src/components/dreamarchive/StudyCard.tsx
Normal file
73
src/components/dreamarchive/StudyCard.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import {FaFlask} from 'react-icons/fa';
|
||||
import {getBackgroundStyle, getTextStyle} from '../../styles/StyleUtils';
|
||||
import IconWithBackground from './IconWithBackground';
|
||||
|
||||
interface StudyCardProps {
|
||||
study: {
|
||||
id: number;
|
||||
title: string;
|
||||
institution: string;
|
||||
status: string;
|
||||
statusColor: string;
|
||||
participants?: {
|
||||
current: number;
|
||||
target: number;
|
||||
};
|
||||
endDate: string;
|
||||
description: string;
|
||||
color: 'purple' | 'blue' | 'violet' | 'emerald' | 'amber' | 'rose' | 'pink-red' | 'cta';
|
||||
};
|
||||
}
|
||||
|
||||
export const StudyCard: React.FC<StudyCardProps> = ({study}) => {
|
||||
return (
|
||||
<div className="dreamy-card p-6 flex flex-col h-full" style={getBackgroundStyle(study.color)}>
|
||||
<div className="flex items-center mb-4">
|
||||
<IconWithBackground
|
||||
icon={<FaFlask/>}
|
||||
color={study.color}
|
||||
size={28}
|
||||
className="mr-4"
|
||||
/>
|
||||
<div>
|
||||
<h3 className="text-lg font-bold dreamy-text">{study.title}</h3>
|
||||
<p className="text-xs" style={getTextStyle('muted')}>{study.institution}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<div className="flex justify-between mb-2">
|
||||
<span className="text-sm font-bold">Status:</span>
|
||||
<span
|
||||
className={`text-sm bg-${study.statusColor}-100 dark:bg-${study.statusColor}-900 text-${study.statusColor}-800 dark:text-${study.statusColor}-200 px-2 py-0.5 rounded-full`}>
|
||||
{study.status}
|
||||
</span>
|
||||
</div>
|
||||
{study.participants && (
|
||||
<div className="flex justify-between mb-2">
|
||||
<span className="text-sm font-bold">Teilnehmer:</span>
|
||||
<span className="text-sm">
|
||||
{study.participants.current.toLocaleString()} / {study.participants.target.toLocaleString()}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-bold">Enddatum:</span>
|
||||
<span className="text-sm">{study.endDate}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm mb-4">
|
||||
{study.description}
|
||||
</p>
|
||||
|
||||
<button
|
||||
className={`w-full py-2 px-4 bg-${study.color}-500 hover:bg-${study.color}-600 text-white rounded-lg transition-colors mt-auto`}>
|
||||
Teilnehmen
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StudyCard;
|
25
src/components/dreamarchive/VideoPlayer.tsx
Normal file
25
src/components/dreamarchive/VideoPlayer.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import {FaVideo} from 'react-icons/fa';
|
||||
|
||||
interface VideoPlayerProps {
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const VideoPlayer: React.FC<VideoPlayerProps> = ({color}) => {
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="aspect-video bg-gray-200 dark:bg-gray-700 rounded-lg flex items-center justify-center">
|
||||
<FaVideo className="text-gray-400 dark:text-gray-500" size={32}/>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<div
|
||||
className={`w-12 h-12 rounded-full bg-${color}-500/80 flex items-center justify-center cursor-pointer`}>
|
||||
<div
|
||||
className="w-0 h-0 border-t-8 border-b-8 border-l-12 border-transparent border-l-white ml-1"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VideoPlayer;
|
24
src/data/MockDailyHighlights.ts
Normal file
24
src/data/MockDailyHighlights.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Mock data for daily highlights on the home page
|
||||
* Contains top dream topics and mood categories with their percentages
|
||||
*/
|
||||
|
||||
// Top dream topics with percentages
|
||||
export const topDreamTopics = [
|
||||
{label: "Fliegen", percentage: 28},
|
||||
{label: "Verfolgung", percentage: 22},
|
||||
{label: "Wasser", percentage: 17}
|
||||
];
|
||||
|
||||
// Primary mood categories with percentages
|
||||
export const primaryMoodCategories = [
|
||||
{label: "Neugier", percentage: 35},
|
||||
{label: "Freude", percentage: 30},
|
||||
{label: "Angst", percentage: 20},
|
||||
{label: "Überraschung", percentage: 15}
|
||||
];
|
||||
|
||||
export default {
|
||||
topDreamTopics,
|
||||
primaryMoodCategories
|
||||
};
|
@@ -1,84 +1,246 @@
|
||||
import Dream, {type ImageInput, type TextInput} from '../types/Dream.ts';
|
||||
import Dream, {type AudioInput, type ChipInput, type ImageInput, type TextInput} from '../types/Dream.ts';
|
||||
|
||||
export const mockDreams: Dream[] = [new Dream({
|
||||
id: 1, userId: 1, title: 'Mitternachtsbibliothek', date: new Date('2025-06-30T02:15:00Z'), input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich wanderte um Mitternacht in eine riesige Bibliothek, in der jedes Buch sanft leuchtete. Als ich eines aus dem Regal zog, flüsterten seine Seiten mir Geheimnisse zu.',
|
||||
} as TextInput, ai: {
|
||||
interpretation: 'Dieses Bild symbolisiert den Wunsch nach Wissen und die Faszination für ungelüftete Geheimnisse. Die leuchtenden Bücher stehen für Inspiration und Erkenntnis, während die nächtliche Atmosphäre auf Introspektion und das Unbewusste hinweist.',
|
||||
image: '01.png',
|
||||
video: '01.mp4',
|
||||
audio: '01.mp3',
|
||||
}
|
||||
}), new Dream({
|
||||
id: 2, userId: 2, title: 'Unterwasserkonzert', date: new Date('2025-06-25T07:45:00Z'), input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich besuchte ein Konzert unter dem Ozean. Die Musiker waren Delfine, die Melodien anklickten, während Korallenpolypen im Takt zum Rhythmus mit Licht pulsierten.',
|
||||
} as TextInput, ai: {
|
||||
interpretation: 'Das Unterwasserkonzert kann als Ausdruck von Kreativität und Harmonie gedeutet werden. Delfine symbolisieren Intelligenz und Spielfreude, Korallenlicht verweist auf emotionale Schwingungen und die Verbindung zum Inneren.',
|
||||
image: '02.png',
|
||||
video: '02.mp4',
|
||||
}
|
||||
}), new Dream({
|
||||
id: 3, userId: 3, title: 'Wüstenzug', date: new Date('2025-05-10T04:30:00Z'), input: {
|
||||
inputType: 'text',
|
||||
input: 'Ein Dampflok-Express tuckerte über goldene Dünen unter einem violetten Himmel. Passagiere winkten, während Kamele mit Laternen neben den Schienen herliefen.',
|
||||
} as TextInput, ai: {
|
||||
interpretation: 'Der Wüstenzug steht für eine Reise durch unbewusste Räume und persönliche Herausforderungen (Dünen). Der violette Himmel deutet auf Spiritualität hin, während die Laternen der Kamele Hoffnung und Wegweisung symbolisieren.',
|
||||
image: '03.png',
|
||||
video: '03.mp4',
|
||||
}
|
||||
}), new Dream({
|
||||
id: 4, userId: 1, title: 'Schwebende Teeparty', date: new Date('2025-04-18T09:00:00Z'), input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich saß mit Freunden auf einer Wolke zu einer Teeparty. Jede Tasse war mit Sternenstaub gefüllt, und der Himmel um uns herum schimmerte in pastelligen Regenbogenfarben.',
|
||||
} as TextInput, ai: {
|
||||
interpretation: 'Diese Szene steht für Geborgenheit und Gemeinschaft auf einer höheren Ebene. Der Sternenstaub in den Tassen symbolisiert geteilte Träume, die pastelligen Regenbögen zeigen eine optimistische Grundstimmung und Leichtigkeit.',
|
||||
image: '04.png'
|
||||
}
|
||||
}), new Dream({
|
||||
id: 5, userId: 2, title: 'Spiegelgarten', date: new Date('2025-03-05T23:20:00Z'), input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich erkundete einen Garten aus Spiegeln, in denen jeweils eine andere Kindheitserinnerung reflektiert wurde. Als ich einen berührte, hörte ich entferntes Lachen durch das Glas hallen.',
|
||||
} as TextInput, ai: {
|
||||
interpretation: 'Der Spiegelgarten repräsentiert Selbsterkenntnis und Rückblick auf die eigene Vergangenheit. Jeder Spiegel steht für ein Fragment der Erinnerung, das entfernte Lachen deutet auf positive Prägungen und emotionale Verankerung hin.',
|
||||
image: '05.png',
|
||||
audio: '05.mp3'
|
||||
}
|
||||
}), new Dream({
|
||||
id: 6, userId: 1, title: 'Crystal Forest', date: new Date('2025-07-01T03:30:00Z'), input: {
|
||||
inputType: 'image',
|
||||
img: 'crystal_forest.jpg',
|
||||
imgAlt: 'A glowing forest made of crystals under a starry sky',
|
||||
description: 'I wandered through a glowing forest where every tree was made of shimmering crystal, reflecting thousands of stars above.',
|
||||
} as ImageInput, ai: {
|
||||
interpretation: 'The crystal forest represents clarity and the search for inner truth. The reflections of stars symbolize inspiration and the connection between your dreams and aspirations.',
|
||||
audio: 'crystal_forest.mp3',
|
||||
image: 'crystal_forest_ai.png',
|
||||
},
|
||||
}), new Dream({
|
||||
id: 7, userId: 2, title: 'Mirror Lake', date: new Date('2025-07-02T05:15:00Z'), input: {
|
||||
inputType: 'image',
|
||||
img: 'mirror_lake.jpg',
|
||||
imgAlt: 'A perfectly still lake reflecting the moon and clouds',
|
||||
description: 'I stood at the edge of a silent lake, its surface so calm it looked like a perfect mirror, reflecting the moon and drifting clouds.',
|
||||
} as ImageInput, ai: {
|
||||
interpretation: 'The mirror lake suggests self-reflection and emotional calm. The moon and clouds indicate subconscious thoughts and the ever-changing nature of your feelings.',
|
||||
video: 'mirror_lake_ai.mp4',
|
||||
image: 'mirror_lake_ai.png',
|
||||
},
|
||||
}), new Dream({
|
||||
id: 8, userId: 3, title: 'Floating City', date: new Date('2025-07-03T06:50:00Z'), input: {
|
||||
inputType: 'image',
|
||||
img: 'floating_city.jpg',
|
||||
imgAlt: 'A futuristic city floating above the clouds at sunrise',
|
||||
description: 'I explored a futuristic city that floated above the clouds, with golden sunlight streaming through transparent walkways.',
|
||||
} as ImageInput, ai: {
|
||||
interpretation: 'The floating city symbolizes ambition and the desire to rise above limitations. The sunrise and golden light represent hope and new beginnings.',
|
||||
image: 'floating_city_ai.png',
|
||||
},
|
||||
}),
|
||||
// Function to generate a random date between July 3rd, 2025 and July 16th, 2025
|
||||
function getRandomDateInRange() {
|
||||
const start = new Date('2025-07-03T00:00:00Z');
|
||||
const end = new Date('2025-07-16T23:59:59Z');
|
||||
const randomTime = start.getTime() + Math.random() * (end.getTime() - start.getTime());
|
||||
return new Date(randomTime);
|
||||
}
|
||||
|
||||
];
|
||||
export const mockDreams: Dream[] = [
|
||||
// Traum 1
|
||||
new Dream({
|
||||
id: 1,
|
||||
userId: 1,
|
||||
title: 'Mitternachtsbibliothek',
|
||||
date: new Date('2025-07-17T03:25:57Z'),
|
||||
tags: ['Wissen', 'Geheimnisse', 'Inspiration'],
|
||||
input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich wanderte um Mitternacht in eine riesige Bibliothek, in der jedes Buch sanft leuchtete. Als ich eines aus dem Regal zog, flüsterten seine Seiten mir Geheimnisse zu.'
|
||||
} as TextInput,
|
||||
ai: {
|
||||
interpretation: 'Dieses Bild symbolisiert den Wunsch nach Wissen und die Faszination für ungelüftete Geheimnisse. Die leuchtenden Bücher stehen für Inspiration und Erkenntnis, während die nächtliche Atmosphäre auf Introspektion und das Unbewusste hinweist.',
|
||||
image: '01.png',
|
||||
video: '01.mp4',
|
||||
audio: '01.mp3'
|
||||
}
|
||||
}),
|
||||
|
||||
export default mockDreams;
|
||||
// Traum 2
|
||||
new Dream({
|
||||
id: 2,
|
||||
userId: 2,
|
||||
title: 'Unterwasserkonzert',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Kreativität', 'Harmonie', 'Ozean'],
|
||||
input: {
|
||||
inputType: 'audio',
|
||||
transcript: 'Ich besuchte ein Konzert unter dem Ozean. Die Musiker waren Delfine, die Melodien anklickten, während Korallenpolypen im Takt zum Rhythmus mit Licht pulsierten.',
|
||||
audio: 'in_02.mp3'
|
||||
} as AudioInput,
|
||||
ai: {
|
||||
interpretation: 'Das Unterwasserkonzert kann als Ausdruck von Kreativität und Harmonie gedeutet werden. Delfine symbolisieren Intelligenz und Spielfreude, Korallenlicht verweist auf emotionale Schwingungen und die Verbindung zum Inneren.',
|
||||
image: '02.png',
|
||||
audio: '02.mp3',
|
||||
video: '02.mp4'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 3
|
||||
new Dream({
|
||||
id: 3,
|
||||
userId: 3,
|
||||
title: 'Wüstenzug',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Reise', 'Herausforderung', 'Spiritualität'],
|
||||
input: {
|
||||
inputType: 'image',
|
||||
description: 'Ein Dampflok-Express tuckerte über goldene Dünen unter einem violetten Himmel. Passagiere winkten, während Kamele mit Laternen neben den Schienen herliefen.',
|
||||
img: 'in_03.png',
|
||||
imgAlt: ''
|
||||
} as ImageInput,
|
||||
ai: {
|
||||
interpretation: 'Der Wüstenzug steht für eine Reise durch unbewusste Räume und persönliche Herausforderungen (Dünen). Der violette Himmel deutet auf Spiritualität hin, während die Laternen der Kamele Hoffnung und Wegweisung symbolisieren.',
|
||||
image: '03.png',
|
||||
video: '03.mp4',
|
||||
audio: '03.mp3'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 4
|
||||
new Dream({
|
||||
id: 4,
|
||||
userId: 1,
|
||||
title: 'Schwebende Teeparty',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Gemeinschaft', 'Geborgenheit', 'Leichtigkeit'],
|
||||
input: {
|
||||
inputType: 'audio',
|
||||
transcript: 'Ich saß mit Freunden auf einer Wolke zu einer Teeparty. Jede Tasse war mit Sternenstaub gefüllt, und der Himmel um uns herum schimmerte in pastelligen Regenbogenfarben.',
|
||||
audio: 'in_04.mp3',
|
||||
} as AudioInput,
|
||||
ai: {
|
||||
interpretation: 'Diese Szene steht für Geborgenheit und Gemeinschaft auf einer höheren Ebene. Der Sternenstaub in den Tassen symbolisiert geteilte Träume, die pastelligen Regenbögen zeigen eine optimistische Grundstimmung und Leichtigkeit.',
|
||||
image: '04.png',
|
||||
audio: '04.mp3',
|
||||
video: '04.mp4'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 5
|
||||
new Dream({
|
||||
id: 5,
|
||||
userId: 2,
|
||||
title: 'Spiegelgarten',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Selbsterkenntnis', 'Erinnerung', 'Vergangenheit'],
|
||||
input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich erkundete einen Garten aus Spiegeln, in denen jeweils eine andere Kindheitserinnerung reflektiert wurde. Als ich einen berührte, hörte ich entferntes Lachen durch das Glas hallen.'
|
||||
} as TextInput,
|
||||
ai: {
|
||||
interpretation: 'Der Spiegelgarten repräsentiert Selbsterkenntnis und Rückblick auf die eigene Vergangenheit. Jeder Spiegel steht für ein Fragment der Erinnerung, das entfernte Lachen deutet auf positive Prägungen und emotionale Verankerung hin.',
|
||||
image: '05.png',
|
||||
audio: '05.mp3',
|
||||
video: '05.mp4'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 9 (userId 4)
|
||||
new Dream({
|
||||
id: 9,
|
||||
userId: 4,
|
||||
title: 'Quantenreise',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Faszination', 'Parallelwelten', 'Informationsverarbeitung'],
|
||||
input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich reiste durch einen Tunnel aus pulsierenden Datenströmen. Jede Berührung löste neue Realitäten aus, die sich wie Fraktale vor mir entfalteten.'
|
||||
} as TextInput,
|
||||
ai: {
|
||||
interpretation: 'Die Quantenreise symbolisiert deine Faszination für Möglichkeiten und Parallelwelten. Die Datenströme repräsentieren Informationsverarbeitung und Entscheidungsfindung in deinem Unterbewusstsein.',
|
||||
image: '09.png',
|
||||
audio: '09.mp3',
|
||||
video: '09.mp4'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 10 (userId 4)
|
||||
new Dream({
|
||||
id: 10,
|
||||
userId: 4,
|
||||
title: 'Neuronales Netzwerk',
|
||||
date: new Date('2025-07-17T05:28:57Z'),
|
||||
tags: ['KI', 'Bewusstsein', 'Kontrolle'],
|
||||
input: {
|
||||
inputType: 'chip',
|
||||
text: 'Du hast von einem riesigen neuronalen Netzwerk, wo Gedanken als leuchtende Impulse zwischen synaptischen Verbindungen tanzten, geträumt.',
|
||||
eeg: {
|
||||
alpha: [
|
||||
21.49, 19.59, 21.94, 24.57, 19.30, 19.30, 24.74, 22.30, 18.59, 21.63,
|
||||
18.61, 18.60, 20.73, 14.26, 14.83, 18.31, 16.96, 20.94, 17.28, 15.76,
|
||||
24.40, 19.32, 20.20, 15.73, 18.37, 20.33, 16.55, 21.13, 18.20, 19.12,
|
||||
18.19, 25.56, 19.96, 16.83, 22.47, 16.34, 20.63, 14.12, 16.02, 20.59,
|
||||
22.22, 20.51, 19.65, 19.10, 15.56, 17.84, 18.62, 23.17, 21.03, 14.71,
|
||||
20.97, 18.84, 17.97, 21.84, 23.09, 22.79, 17.48, 19.07, 20.99, 22.93
|
||||
],
|
||||
beta: [
|
||||
9.04, 9.63, 7.79, 7.61, 11.63, 12.71, 9.86, 12.01, 10.72, 8.71,
|
||||
10.72, 13.08, 9.93, 13.13, 5.00, 11.64, 10.17, 9.40, 10.18, 6.02,
|
||||
9.56, 10.71, 12.96, 8.96, 8.38, 8.99, 11.83, 10.66, 8.94, 11.03,
|
||||
10.19, 11.94, 8.60, 9.34, 9.22, 7.07, 10.59, 10.52, 10.01, 9.53,
|
||||
7.17, 9.16, 9.31, 8.40, 9.68, 10.81, 13.77, 10.35, 10.52, 9.85,
|
||||
6.16, 9.95, 10.12, 14.93, 9.62, 10.60, 9.93, 7.66, 12.29, 11.50
|
||||
],
|
||||
theta: [
|
||||
33.96, 25.45, 37.01, 22.99, 32.93, 40.00, 25.05, 27.17, 30.50, 27.48,
|
||||
22.25, 30.34, 24.69, 32.37, 25.40, 37.75, 26.08, 28.39, 34.07, 23.85,
|
||||
31.14, 36.54, 21.96, 30.92, 31.30, 33.91, 23.82, 23.40, 32.61, 31.48,
|
||||
31.25, 31.73, 26.60, 31.16, 31.47, 26.43, 39.33, 32.37, 24.04, 33.28,
|
||||
25.13, 33.94, 35.79, 25.90, 34.82, 32.06, 34.11, 39.48, 28.77, 26.23,
|
||||
25.55, 25.92, 29.61, 31.71, 31.38, 34.13, 30.07, 37.27, 28.68, 40.00
|
||||
],
|
||||
delta: [
|
||||
43.75, 34.86, 33.57, 42.89, 38.66, 44.28, 42.84, 39.56, 34.92, 30.91,
|
||||
37.32, 45.14, 41.28, 32.53, 41.04, 42.31, 34.70, 40.92, 40.35, 33.14,
|
||||
42.15, 43.36, 46.50, 46.32, 31.73, 34.37, 43.09, 43.08, 43.09, 50.00,
|
||||
43.43, 46.81, 45.72, 43.91, 38.11, 44.55, 35.36, 38.58, 37.09, 40.49,
|
||||
50.00, 30.00, 44.12, 30.32, 37.17, 46.53, 40.39, 33.53, 35.71, 44.08,
|
||||
35.62, 41.30, 40.27, 36.09, 50.00, 43.80, 30.00, 41.12, 36.03, 45.11
|
||||
]
|
||||
},
|
||||
puls: [
|
||||
62.62, 64.66, 66.51, 67.60, 61.40, 64.00, 63.58, 63.04, 70.00, 66.21,
|
||||
61.22, 67.75, 70.00, 68.10, 60.44, 63.55, 68.80, 62.88, 66.33, 67.32,
|
||||
62.22, 64.82, 60.00, 61.93, 64.24, 61.26, 69.90, 60.71, 63.68, 65.39,
|
||||
69.32, 60.69, 68.49, 65.03, 62.06, 66.39, 65.60, 63.20, 65.21, 63.84,
|
||||
65.34, 66.99, 69.76, 61.29, 70.00, 60.00, 64.54, 66.76, 65.84, 63.13,
|
||||
64.38, 63.52, 63.23, 67.55, 66.07, 62.92, 67.70, 65.92, 67.44, 66.89
|
||||
],
|
||||
hrv: [
|
||||
60.61, 57.89, 60.71, 57.86, 67.10, 62.59, 69.24, 60.96, 52.74, 56.56,
|
||||
66.48, 59.99, 54.13, 57.87, 70.00, 63.01, 55.81, 62.69, 58.96, 54.70,
|
||||
66.05, 63.33, 65.91, 70.00, 56.49, 61.42, 56.00, 70.00, 65.76, 62.36,
|
||||
51.29, 64.13, 53.40, 56.55, 70.00, 56.49, 54.68, 61.99, 61.65, 59.49,
|
||||
55.21, 57.25, 51.71, 64.89, 47.64, 70.00, 53.67, 49.43, 54.72, 62.67,
|
||||
62.80, 70.00, 67.82, 54.10, 57.76, 59.14, 54.51, 56.71, 56.74, 52.09
|
||||
],
|
||||
bewegung: [
|
||||
0.20, 0.30, 0.14, 0.19, 0.22, 0.11, 0.17, 0.15, 0.16, 0.07,
|
||||
0.15, 0.20, 0.30, 0.25, 0.37, 0.07, 0.24, 0.17, 0.37, 0.07,
|
||||
0.07, 0.09, 0.00, 0.10, 0.07, 0.17, 0.18, 0.34, 0.25, 0.09,
|
||||
0.06, 0.20, 0.02, 0.33, 0.27, 0.10, 0.00, 0.29, 0.14, 0.27,
|
||||
0.00, 0.09, 0.15, 0.15, 0.10, 0.21, 0.04, 0.14, 0.16, 0.20,
|
||||
0.22, 0.04, 0.00, 0.28, 0.18, 0.08, 0.31, 0.16, 0.27, 0.16
|
||||
]
|
||||
} as ChipInput,
|
||||
ai: {
|
||||
interpretation: 'Das neuronale Netzwerk spiegelt dein Interesse an künstlicher Intelligenz und dem menschlichen Bewusstsein wider. Die Fähigkeit, Gedanken zu formen, deutet auf deinen Wunsch nach Kontrolle über deine mentalen Prozesse hin.',
|
||||
audio: '10.mp3',
|
||||
image: '10.png',
|
||||
video: '10.mp4'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 11 (userId 4)
|
||||
new Dream({
|
||||
id: 11,
|
||||
userId: 4,
|
||||
title: 'Digitaler Garten',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Natur', 'Technologie', 'Innovation'],
|
||||
input: {
|
||||
inputType: 'image',
|
||||
img: 'in_11.png',
|
||||
imgAlt: 'Ein Garten aus leuchtenden Codezeilen und holografischen Pflanzen',
|
||||
description: 'Leuchtende, halb-transparente Pflanzen mit holografischen Mustern wachsen in einem futuristischen Garten, in dem organische Formen und digitale Technologien harmonisch verschmelzen. Farbenfrohe Lichter ziehen sich an den Ästen entlang und schaffen eine friedliche, zukunftsweisende Atmosphäre.'
|
||||
} as ImageInput,
|
||||
ai: {
|
||||
interpretation: 'Der digitale Garten verkörpert deine kreative Verbindung von Natur und Technologie. Er zeigt, wie du Innovation als organischen, wachsenden Prozess betrachtest.',
|
||||
audio: '11.mp3',
|
||||
image: '11.png',
|
||||
video: '11.mp4'
|
||||
}
|
||||
}),
|
||||
|
||||
// Traum 12 (userId 4)
|
||||
new Dream({
|
||||
id: 12,
|
||||
userId: 4,
|
||||
title: 'Zeitschleife',
|
||||
date: getRandomDateInRange(),
|
||||
tags: ['Kausalität', 'Entscheidungen', 'Realität'],
|
||||
input: {
|
||||
inputType: 'text',
|
||||
input: 'Ich erlebte denselben Tag immer wieder, konnte aber jedes Mal kleine Änderungen vornehmen. Mit jeder Iteration wurde die Realität komplexer und unvorhersehbarer.'
|
||||
} as TextInput,
|
||||
ai: {
|
||||
interpretation: 'Die Zeitschleife reflektiert deine Gedanken über Kausalität und die Auswirkungen kleiner Entscheidungen. Sie symbolisiert auch den Wunsch, Fehler zu korrigieren und verschiedene Möglichkeiten zu erkunden.',
|
||||
audio: '12.mp3',
|
||||
image: '12.png',
|
||||
video: '12.mp4'
|
||||
}
|
||||
})
|
||||
];
|
144
src/data/MockResearchLive.ts
Normal file
144
src/data/MockResearchLive.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
// Updated MockResearchLive.ts
|
||||
|
||||
type ColorType = 'purple' | 'blue' | 'violet' | 'emerald' | 'amber' | 'rose' | 'pink-red' | 'cta';
|
||||
|
||||
interface Study {
|
||||
id: number;
|
||||
title: string;
|
||||
institution: string;
|
||||
status: string;
|
||||
statusColor: string;
|
||||
participants?: { current: number; target: number };
|
||||
endDate: string;
|
||||
description: string;
|
||||
color: ColorType;
|
||||
}
|
||||
|
||||
interface CitizenScienceProject {
|
||||
id: number;
|
||||
title: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
optedIn: boolean;
|
||||
}
|
||||
|
||||
interface Event {
|
||||
id: number;
|
||||
date: string;
|
||||
title: string;
|
||||
location: string;
|
||||
type: string;
|
||||
typeColor: string;
|
||||
}
|
||||
|
||||
export const currentStudies: Study[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Kulturübergreifende Traumsymbole",
|
||||
institution: "University of Tokyo, Japan",
|
||||
status: "Aktiv",
|
||||
statusColor: "green",
|
||||
participants: {current: 3456, target: 10000},
|
||||
endDate: "31. Dezember 2025",
|
||||
description:
|
||||
"Diese globale Studie sammelt Traumsymbole aus verschiedenen Kulturen, um universelle und kulturspezifische Traumelemente zu identifizieren.",
|
||||
color: "amber",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Time course of the lucid dream experience",
|
||||
institution: "Organization for Lucid Dream Studies",
|
||||
status: "Laufend",
|
||||
statusColor: "green",
|
||||
endDate: "April 2026",
|
||||
description:
|
||||
"Untersuchung, wann und wie Träume in luzide Träume übergehen und was danach geschieht.",
|
||||
color: "violet",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Reality monitoring & state test reliability",
|
||||
institution: "Organization for Lucid Dream Studies",
|
||||
status: "Laufend",
|
||||
statusColor: "green",
|
||||
endDate: "August 2027",
|
||||
description:
|
||||
"Vergleich von Reality-Monitoring-Fehlern und Traum-Wach-Verwechslungen in Bezug auf die Häufigkeit luzider Träume.",
|
||||
color: "pink-red",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "Rapid Eye Movement Restoration and Enhancement for Sleep-deprived Trauma-adaptation",
|
||||
institution: "University of Wisconsin–Madison, USA",
|
||||
status: "Laufend",
|
||||
statusColor: "green",
|
||||
endDate: "31. August 2025",
|
||||
description:
|
||||
"Untersuchung, ob gezielte REM-Schlaf-Wiederherstellung und -Förderung bei schlafentzugbedingten Traumafolgestörungen die Symptome lindert und die Erholung verbessert.",
|
||||
color: "emerald",
|
||||
},
|
||||
];
|
||||
|
||||
export const citizenScienceProjects: CitizenScienceProject[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Globales Traumtagebuch",
|
||||
icon: "FaClipboardCheck",
|
||||
description:
|
||||
"Teile deine Träume in der weltweit größten Traumdatenbank und hilf Forschern, Muster zu erkennen.",
|
||||
optedIn: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Traumkarte",
|
||||
icon: "FaGlobeEurope",
|
||||
description:
|
||||
"Hilf bei der Erstellung einer interaktiven Weltkarte, die zeigt, wie Träume je nach Region variieren.",
|
||||
optedIn: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Kulturelle Traumlandschaften",
|
||||
icon: "FaUsers",
|
||||
description:
|
||||
"Teile deine demographischen Daten und hilf bei der Untersuchung der Auswirkung von Kultur aufs Träumen.",
|
||||
optedIn: false,
|
||||
}
|
||||
];
|
||||
|
||||
export const upcomingEvents: Event[] = [
|
||||
{
|
||||
id: 1,
|
||||
date: "16. August 2025",
|
||||
title: "Regional Dream Conference",
|
||||
location: "Ort wird noch bekanntgegeben",
|
||||
type: "Konferenz",
|
||||
typeColor: "emerald",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
date: "26. September 2025 – 27. September 2025",
|
||||
title: "Regional Dream Conference",
|
||||
location: "Bridgewater State University, USA",
|
||||
type: "Konferenz",
|
||||
typeColor: "emerald",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
date: "10. Oktober 2025 – 12. Oktober 2025",
|
||||
title: "Internationale Jahreskonferenz der IASD",
|
||||
location: "Ort wird noch bekanntgegeben",
|
||||
type: "Konferenz",
|
||||
typeColor: "emerald",
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
currentStudies,
|
||||
citizenScienceProjects,
|
||||
upcomingEvents
|
||||
} as {
|
||||
currentStudies: Study[];
|
||||
citizenScienceProjects: CitizenScienceProject[];
|
||||
upcomingEvents: Event[];
|
||||
};
|
111
src/data/MockUserDreams.ts
Normal file
111
src/data/MockUserDreams.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Mock data for the UserDreams page
|
||||
* Contains user dream profile statistics and comparisons
|
||||
*/
|
||||
|
||||
// User's most frequent dream themes
|
||||
export const userDreamThemes = [
|
||||
{theme: "Fliegen", percentage: 32, color: "purple"},
|
||||
{theme: "Technologie", percentage: 28, color: "blue"},
|
||||
{theme: "Kreativität", percentage: 24, color: "emerald"}
|
||||
];
|
||||
|
||||
// Global comparison data for dream emotions
|
||||
export const dreamEmotionsComparison = {
|
||||
positive: {
|
||||
global: 42,
|
||||
user: 58,
|
||||
color: "blue"
|
||||
},
|
||||
negative: {
|
||||
global: 38,
|
||||
user: 22,
|
||||
color: "red"
|
||||
},
|
||||
neutral: {
|
||||
global: 20,
|
||||
user: 20,
|
||||
color: "yellow"
|
||||
}
|
||||
};
|
||||
|
||||
// Dream themes comparison data
|
||||
export const dreamThemesComparison = {
|
||||
userTopThemes: [
|
||||
{theme: "Fliegen", percentage: 32},
|
||||
{theme: "Technologie", percentage: 28},
|
||||
{theme: "Kreativität", percentage: 24},
|
||||
{theme: "Reisen", percentage: 10},
|
||||
{theme: "Musik", percentage: 6}
|
||||
],
|
||||
globalTopThemes: [
|
||||
{theme: "Fallen", percentage: 28},
|
||||
{theme: "Verfolgung", percentage: 22},
|
||||
{theme: "Fliegen", percentage: 18},
|
||||
{theme: "Prüfungen", percentage: 16},
|
||||
{theme: "Verlust", percentage: 14}
|
||||
]
|
||||
};
|
||||
|
||||
// Unique aspects of user's dreams
|
||||
export const uniqueDreamAspects = [
|
||||
"Deine Träume enthalten 55% mehr technologische Elemente als der Durchschnitt",
|
||||
"Du träumst 78% häufiger vom Fliegen als die meisten Menschen",
|
||||
"Kreative Problemlösung tritt in deinen Träumen 3x häufiger auf"
|
||||
];
|
||||
|
||||
// Dream theme timeline data
|
||||
export const dreamThemeTimeline = {
|
||||
timePoints: ["März 2023", "Juni 2023", "Sept 2023", "Dez 2023", "März 2024", "Heute"],
|
||||
themes: [
|
||||
{
|
||||
name: "Fliegen",
|
||||
color: "#8b5cf6", // purple
|
||||
dataPoints: [70, 65, 50, 40, 30, 20] // y-values (0-100)
|
||||
},
|
||||
{
|
||||
name: "Technologie",
|
||||
color: "#3b82f6", // blue
|
||||
dataPoints: [80, 75, 70, 60, 50, 30]
|
||||
},
|
||||
{
|
||||
name: "Kreativität",
|
||||
color: "#10b981", // emerald
|
||||
dataPoints: [85, 80, 75, 65, 55, 35]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Key insights from dream analysis
|
||||
export const dreamInsights = [
|
||||
"Deine Träume vom Fliegen haben im letzten Jahr um 60% zugenommen",
|
||||
"Technologiebezogene Träume sind seit Dezember 2023 um 40% gestiegen",
|
||||
"Kreative Elemente in deinen Träumen haben sich verdoppelt",
|
||||
"Angstträume haben um 45% abgenommen"
|
||||
];
|
||||
|
||||
// Personalized recommendations
|
||||
export const dreamRecommendations = {
|
||||
forDreamWork: [
|
||||
"Experimentiere mit luziden Träumen, da deine Flugträume ein guter Ausgangspunkt sind",
|
||||
"Führe ein detaillierteres Traumtagebuch, um Muster in deinen technologiebezogenen Träumen zu erkennen",
|
||||
"Probiere geführte Meditationen vor dem Schlafengehen, um deine kreativen Träume zu verstärken",
|
||||
"Teile deine Traumgeschichten in der Community, um neue Perspektiven zu gewinnen"
|
||||
],
|
||||
basedOnProfile: [
|
||||
"Entdecke unsere Sammlung von Flugträumen aus verschiedenen Kulturen",
|
||||
"Nimm an unserem Workshop \"Kreativität im Traum\" teil",
|
||||
"Teste unsere neue Funktion zur Traumvisualisierung",
|
||||
"Verbinde dich mit anderen Träumern, die ähnliche Interessen an Technologie und Innovation haben"
|
||||
]
|
||||
};
|
||||
|
||||
export default {
|
||||
userDreamThemes,
|
||||
dreamEmotionsComparison,
|
||||
dreamThemesComparison,
|
||||
uniqueDreamAspects,
|
||||
dreamThemeTimeline,
|
||||
dreamInsights,
|
||||
dreamRecommendations
|
||||
};
|
106
src/data/MockWorldwideEvents.ts
Normal file
106
src/data/MockWorldwideEvents.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Mock data for the WorldwideEvents page
|
||||
* Contains timeline events and detailed event analysis data
|
||||
*/
|
||||
|
||||
// Timeline events data
|
||||
export const timelineEvents = [
|
||||
{
|
||||
year: "2020",
|
||||
event: "Beginn der COVID-19 Pandemie",
|
||||
dreamEffect: "40% Anstieg der Traumhäufigkeit während Lockdown",
|
||||
dreamEffectDetail: "Basierend auf 1.622 Teilnehmern in Italien"
|
||||
},
|
||||
{
|
||||
year: "2021",
|
||||
event: "Klimawandel-Ereignisse intensivieren sich",
|
||||
dreamEffect: "23% mehr Träume über Feuer und Flucht",
|
||||
dreamEffectDetail: "Korreliert mit Waldbränden in Australien und Kalifornien"
|
||||
},
|
||||
{
|
||||
year: "2022",
|
||||
event: "Beginn des Konflikts in der Ukraine",
|
||||
dreamEffect: "Erhöhte Angstträume in europäischen Nachbarländern",
|
||||
dreamEffectDetail: "Besonders in Polen, Rumänien und den baltischen Staaten"
|
||||
},
|
||||
{
|
||||
year: "2023",
|
||||
event: "Wirtschaftliche Instabilität",
|
||||
dreamEffect: "Verstärkte Träume über Jobverlust und finanzielle Sorgen",
|
||||
dreamEffectDetail: "Korreliert mit globaler Wirtschaftskrise"
|
||||
},
|
||||
{
|
||||
year: "2024-2025",
|
||||
event: "Extreme Wetterereignisse nehmen zu",
|
||||
dreamEffect: "Verstärkte Wasserträume in von Überschwemmungen betroffenen Regionen",
|
||||
dreamEffectDetail: "Hitzewellen führten zu fragmentierten Träumen durch veränderte Schlafmuster"
|
||||
}
|
||||
];
|
||||
|
||||
// Detailed event analysis data
|
||||
export const detailedEvents = [
|
||||
{
|
||||
id: 1,
|
||||
title: "COVID-19 Pandemie (2020-2022)",
|
||||
icon: "FaVirus",
|
||||
color: "purple",
|
||||
details: [
|
||||
{
|
||||
title: "Traumhäufigkeit",
|
||||
description: "1.622 Teilnehmer in Italien berichteten einen 40% Anstieg der Traumhäufigkeit während des Lockdowns"
|
||||
},
|
||||
{
|
||||
title: "Emotionale Auswirkungen",
|
||||
description: "Negative Traumemotionen korrelierten direkt mit Schlafqualitätsverschlechterung"
|
||||
},
|
||||
{
|
||||
title: "Häufige Themen",
|
||||
description: "Isolation, Krankheit, Verlust von Kontrolle"
|
||||
}
|
||||
],
|
||||
summary: "Die COVID-19 Pandemie hatte einen signifikanten Einfluss auf die Traumlandschaft weltweit. Studien zeigen, dass Menschen während der Lockdown-Phasen häufiger und intensiver träumten, wobei negative Emotionen und Ängste dominierten."
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Klimawandel-Ereignisse (2021-2025)",
|
||||
icon: "FaFire",
|
||||
color: "emerald",
|
||||
details: [
|
||||
{
|
||||
title: "Waldbrände",
|
||||
description: "Waldbrände in Australien/Kalifornien führten zu 23% mehr Träumen über Feuer und Flucht"
|
||||
},
|
||||
{
|
||||
title: "Überschwemmungen",
|
||||
description: "Überschwemmungen in Europa führten zu verstärkten Wasserträumen in betroffenen Regionen"
|
||||
},
|
||||
{
|
||||
title: "Hitzewellen",
|
||||
description: "Veränderte Schlafmuster durch Hitzewellen führten zu fragmentierten Träumen"
|
||||
}
|
||||
],
|
||||
summary: "Klimawandel-Ereignisse spiegeln sich deutlich in den Traummustern wider. Besonders bemerkenswert ist, dass Menschen in direkt betroffenen Regionen häufiger von den spezifischen Naturkatastrophen träumen, die sie erlebt haben."
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Geopolitische Spannungen (2022-2025)",
|
||||
icon: "FaFlag",
|
||||
color: "blue",
|
||||
details: [
|
||||
{
|
||||
title: "Konflikt in der Ukraine",
|
||||
description: "Erhöhte Angstträume in europäischen Nachbarländern, besonders in Polen, Rumänien und den baltischen Staaten"
|
||||
},
|
||||
{
|
||||
title: "Wirtschaftskrise",
|
||||
description: "Verstärkte Träume über Jobverlust und finanzielle Sorgen, korrelierend mit globaler wirtschaftlicher Instabilität"
|
||||
}
|
||||
],
|
||||
summary: "Geopolitische Spannungen und Konflikte haben einen messbaren Einfluss auf die Traumlandschaft, wobei die Nähe zum Konfliktgebiet die Intensität der Traumreaktionen beeinflusst. Wirtschaftliche Unsicherheit spiegelt sich in Träumen über finanzielle Sorgen wider."
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
timelineEvents,
|
||||
detailedEvents
|
||||
};
|
492
src/index.css
492
src/index.css
@@ -1,362 +1,414 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--bg: #f9f6ff;
|
||||
--container: #eee8fc;
|
||||
--card: #e5dcff;
|
||||
--text: #1a0d29;
|
||||
--text-muted: #3d2a5c;
|
||||
--accent: #a64dff;
|
||||
--accent-gradient: linear-gradient(135deg, #a64dff, #d500f9);
|
||||
--accent-soft: #c9a4ff;
|
||||
--accent-dark: #6a0dad;
|
||||
--shadow: rgba(166, 77, 255, 0.2);
|
||||
--text-shadow: rgba(0, 0, 0, 0.5);
|
||||
--bg: #f9f6ff;
|
||||
--container: #eee8fc;
|
||||
--card: #e5dcff;
|
||||
--text: #1a0d29;
|
||||
--text-muted: #3d2a5c;
|
||||
--accent: #a64dff;
|
||||
--accent-gradient: linear-gradient(135deg, #a64dff, #d500f9);
|
||||
--accent-soft: #c9a4ff;
|
||||
--accent-dark: #6a0dad;
|
||||
--shadow: rgba(166, 77, 255, 0.2);
|
||||
--text-shadow: rgba(0, 0, 0, 0.5);
|
||||
|
||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
/* Additional dreamy gradients from Overview page */
|
||||
--purple-gradient: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
--blue-gradient: linear-gradient(135deg, rgba(59, 130, 246, 0.35), rgba(79, 70, 229, 0.35));
|
||||
--violet-gradient: linear-gradient(135deg, rgba(139, 92, 246, 0.35), rgba(124, 58, 237, 0.35));
|
||||
--emerald-gradient: linear-gradient(135deg, rgba(16, 185, 129, 0.35), rgba(20, 184, 166, 0.35));
|
||||
--amber-gradient: linear-gradient(135deg, rgba(245, 158, 11, 0.35), rgba(249, 115, 22, 0.35));
|
||||
--rose-gradient: linear-gradient(135deg, rgba(244, 63, 94, 0.35), rgba(236, 72, 153, 0.35));
|
||||
--pink-red-gradient: linear-gradient(135deg, rgba(236, 72, 153, 0.3), rgba(239, 68, 68, 0.3));
|
||||
--cta-gradient: linear-gradient(135deg, #ec4899, #8b5cf6, #a855f7);
|
||||
|
||||
color-scheme: light dark;
|
||||
color: var(--text);
|
||||
background-color: var(--bg);
|
||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color-scheme: light dark;
|
||||
color: var(--text);
|
||||
background-color: var(--bg);
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--bg: #150830;
|
||||
--container: #2a1050;
|
||||
--card: #3d1a6e;
|
||||
--text: #f8eeff;
|
||||
--text-muted: #d4b8f0;
|
||||
--accent: #c490ff;
|
||||
--accent-gradient: linear-gradient(135deg, #c490ff, #d500f9);
|
||||
--accent-soft: #a64dff;
|
||||
--accent-dark: #6a0dad;
|
||||
--shadow: rgba(196, 144, 255, 0.3);
|
||||
--text-shadow: rgba(255, 255, 255, 0.5);
|
||||
--bg: #150830;
|
||||
--container: #2a1050;
|
||||
--card: #3d1a6e;
|
||||
--text: #f8eeff;
|
||||
--text-muted: #d4b8f0;
|
||||
--accent: #c490ff;
|
||||
--accent-gradient: linear-gradient(135deg, #c490ff, #d500f9);
|
||||
--accent-soft: #a64dff;
|
||||
--accent-dark: #6a0dad;
|
||||
--shadow: rgba(196, 144, 255, 0.3);
|
||||
--text-shadow: rgba(255, 255, 255, 0.5);
|
||||
|
||||
/* Dark theme dreamy gradients */
|
||||
--purple-gradient: linear-gradient(135deg, rgba(166, 77, 255, 0.3), rgba(213, 0, 249, 0.3));
|
||||
--blue-gradient: linear-gradient(135deg, rgba(59, 130, 246, 0.3), rgba(79, 70, 229, 0.3));
|
||||
--violet-gradient: linear-gradient(135deg, rgba(139, 92, 246, 0.3), rgba(124, 58, 237, 0.3));
|
||||
--emerald-gradient: linear-gradient(135deg, rgba(16, 185, 129, 0.3), rgba(20, 184, 166, 0.3));
|
||||
--amber-gradient: linear-gradient(135deg, rgba(245, 158, 11, 0.3), rgba(249, 115, 22, 0.3));
|
||||
--rose-gradient: linear-gradient(135deg, rgba(244, 63, 94, 0.3), rgba(236, 72, 153, 0.3));
|
||||
--pink-red-gradient: linear-gradient(135deg, rgba(236, 72, 153, 0.25), rgba(239, 68, 68, 0.25));
|
||||
--cta-gradient: linear-gradient(135deg, #ec4899, #8b5cf6, #a855f7);
|
||||
}
|
||||
|
||||
.border-background {
|
||||
border-color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.page {
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
position: relative;
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: radial-gradient(var(--accent-soft) 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
opacity: 0.05;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: radial-gradient(var(--accent-soft) 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
opacity: 0.05;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.pageTitle {
|
||||
color: var(--accent);
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
color: var(--accent);
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.dreamPanel {
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
border-radius: 10px;
|
||||
padding: 1em;
|
||||
color: var(--text);
|
||||
backdrop-filter: blur(5px);
|
||||
box-shadow: 0 0 15px var(--shadow);
|
||||
border: none;
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
border-radius: 10px;
|
||||
padding: 1em;
|
||||
color: var(--text);
|
||||
backdrop-filter: blur(5px);
|
||||
box-shadow: 0 0 15px var(--shadow);
|
||||
border: none;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: var(--accent);
|
||||
text-decoration: inherit;
|
||||
font-weight: 500;
|
||||
color: var(--accent);
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--text-muted);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
overflow-x: hidden;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: var(--container);
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s, background-color 0.3s, color 0.3s;
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: var(--container);
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s, background-color 0.3s, color 0.3s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
.feed-container {
|
||||
padding: 1.5em;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
padding: 1.5em;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
|
||||
.dream-card {
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
border-radius: 12px;
|
||||
padding: 1.25em;
|
||||
color: var(--text);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3);
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
border-radius: 12px;
|
||||
padding: 1.25em;
|
||||
color: var(--text);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3);
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dream-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
margin: -1px;
|
||||
border-radius: inherit;
|
||||
background: var(--accent-gradient);
|
||||
opacity: 0.1;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
margin: -1px;
|
||||
border-radius: inherit;
|
||||
background: var(--accent-gradient);
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.dream-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px var(--shadow), inset 0 0 20px rgba(166, 77, 255, 0.3);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px var(--shadow), inset 0 0 20px rgba(166, 77, 255, 0.3);
|
||||
}
|
||||
|
||||
.dream-card .title {
|
||||
color: var(--accent);
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.3;
|
||||
color: var(--accent);
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.dream-card .timestamp {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.microphone-button {
|
||||
background: var(--accent-gradient);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
|
||||
background: var(--accent-gradient);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Theme Toggle Styles */
|
||||
.theme-toggle {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.theme-toggle input {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.theme-toggle .slider {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background-color: #bbb;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background-color: #bbb;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.theme-toggle .slider::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s;
|
||||
content: "";
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.theme-toggle input:checked + .slider::before {
|
||||
transform: translateX(20px);
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.theme-toggle input:checked + .slider {
|
||||
background-color: var(--accent);
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
/* Dreamy violet enhancements */
|
||||
.dream-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
background: var(--accent-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin-bottom: 0.5rem;
|
||||
text-shadow: 0 1px 2px var(--text-shadow);
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
background: var(--accent-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin-bottom: 0.5rem;
|
||||
text-rendering: geometricPrecision;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.dream-container {
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.25), rgba(213, 0, 249, 0.25));
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: 0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
transition: transform 0.3s, box-shadow 0.3s;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.25), rgba(213, 0, 249, 0.25));
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: 0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
transition: transform 0.3s, box-shadow 0.3s;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dream-container:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px var(--shadow), inset 0 0 20px rgba(166, 77, 255, 0.3);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px var(--shadow), inset 0 0 20px rgba(166, 77, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--bg);
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--accent-soft);
|
||||
border-radius: 5px;
|
||||
background: var(--accent-soft);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--accent);
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
/* Dreamy Card Styling */
|
||||
.dreamy-card {
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
border-radius: 12px;
|
||||
padding: 1.25em;
|
||||
color: var(--text);
|
||||
background: linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35));
|
||||
border-radius: 12px;
|
||||
padding: 1.25em;
|
||||
color: var(--text);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dreamy-card:hover {
|
||||
transform: translateY(-5px);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px var(--shadow), inset 0 0 20px rgba(166, 77, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes dream-float {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradient-animation {
|
||||
0% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.floating {
|
||||
animation: dream-float 6s ease-in-out infinite;
|
||||
animation: dream-float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Custom animations */
|
||||
.animate-fadeIn {
|
||||
animation: fadeIn 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
p {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.feed-container {
|
||||
padding: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.dream-card {
|
||||
padding: 1em;
|
||||
}
|
||||
p {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.dream-card .title {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.feed-container {
|
||||
padding: 1.2em;
|
||||
}
|
||||
|
||||
.dream-card {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.dream-card .title {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.page {
|
||||
padding: 0.75rem !important;
|
||||
}
|
||||
.page {
|
||||
padding: 0.75rem !important;
|
||||
}
|
||||
|
||||
.feed-container {
|
||||
padding: 1em 0.75em;
|
||||
}
|
||||
.feed-container {
|
||||
padding: 1em 0.75em;
|
||||
}
|
||||
|
||||
.dream-card {
|
||||
padding: 0.9em;
|
||||
}
|
||||
.dream-card {
|
||||
padding: 0.9em;
|
||||
}
|
||||
|
||||
.dream-card .title {
|
||||
font-size: 1em;
|
||||
}
|
||||
.dream-card .title {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.dream-card img {
|
||||
width: 2.5rem !important;
|
||||
height: 2.5rem !important;
|
||||
}
|
||||
.dream-card img {
|
||||
width: 2.5rem !important;
|
||||
height: 2.5rem !important;
|
||||
}
|
||||
}
|
||||
|
373
src/pages/ChipOverview.tsx
Normal file
373
src/pages/ChipOverview.tsx
Normal file
@@ -0,0 +1,373 @@
|
||||
import {BsMoonStars, BsStars} from 'react-icons/bs';
|
||||
import {
|
||||
FaBrain,
|
||||
FaChartBar,
|
||||
FaCloud,
|
||||
FaFlask,
|
||||
FaHeart,
|
||||
FaHeartbeat,
|
||||
FaMicrochip,
|
||||
FaPlug,
|
||||
FaRunning,
|
||||
FaShieldAlt,
|
||||
FaUniversity,
|
||||
FaUserMd,
|
||||
FaUsers,
|
||||
} from 'react-icons/fa';
|
||||
import {HiSparkles} from 'react-icons/hi';
|
||||
|
||||
export default function ChipOverview() {
|
||||
return (<div className="p-4 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Floating Background Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<div className="absolute top-20 left-0 text-purple-200 opacity-30">
|
||||
<FaCloud size={40}/>
|
||||
</div>
|
||||
<div className="absolute top-60 right-5 text-purple-300 opacity-20">
|
||||
<BsStars size={30}/>
|
||||
</div>
|
||||
<div className="absolute bottom-10 left-32 text-purple-200 opacity-25">
|
||||
<BsMoonStars size={35}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div className="animate-pulse flex flex-col items-center mb-8 sm:mb-12">
|
||||
<div className="flex items-center justify-around">
|
||||
<h1 className="text-9xl sm:text-7xl font-bold text-purple-500 dark:text-purple-400">REMsense</h1>
|
||||
</div>
|
||||
<p className="text-lg sm:text-xl dreamy-text">Bahnbrechende Traumtechnologie</p>
|
||||
</div>
|
||||
<div
|
||||
className="dream-container floating max-w-3xl mx-auto backdrop-blur-sm bg-white/10 dark:bg-white/5 rounded-3xl p-4 sm:p-6 md:p-8"
|
||||
style={{animationDelay: '0.2s'}}>
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-3 sm:mb-4">
|
||||
<HiSparkles className="text-yellow-400 mb-2 sm:mb-0 sm:mr-2" size={20}/>
|
||||
<h2 className="dream-title text-xl sm:text-2xl">Der erste aufklebbare Sensor-Chip für vollständige
|
||||
Traumerfassung</h2>
|
||||
<HiSparkles className="text-yellow-400 mt-2 sm:mt-0 sm:ml-2 hidden sm:block" size={20}/>
|
||||
</div>
|
||||
<p className="mb-4 sm:mb-6 md:mb-8 text-sm sm:text-base md:text-lg" style={{color: 'var(--text)'}}>
|
||||
Unser innovativer Chip vereint drei revolutionäre Technologien in einem einzigen, aufklebbaren
|
||||
Sensorsystem
|
||||
mit KI-gestützter Inhaltsanalyse
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Features Grid - Dreamy Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
{/* EEG-Sensoren */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6 floating backdrop-blur-md bg-gradient-to-br from-purple-100/50 to-pink-100/50 border border-purple-200/30 dark:bg-gradient-to-br dark:from-purple-900/30 dark:to-pink-900/30 dark:border-purple-700/30"
|
||||
style={{animationDelay: '0.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-purple-500/20 rounded-full">
|
||||
<FaBrain className="text-purple-600 dark:text-purple-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center dreamy-text">
|
||||
EEG-Sensoren
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Erfassung von Hirnströmen zur Traumdetektion mit über 85% Genauigkeit
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Herzfrequenz-Sensoren */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6 floating backdrop-blur-md bg-gradient-to-br from-blue-100/50 to-indigo-100/50 border border-blue-200/30 dark:bg-gradient-to-br dark:from-blue-900/30 dark:to-indigo-900/30 dark:border-blue-700/30"
|
||||
style={{animationDelay: '1s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-blue-500/20 rounded-full">
|
||||
<FaHeartbeat className="text-blue-600 dark:text-blue-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center dreamy-text">
|
||||
Herzfrequenz-Sensoren
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Präzise Pulsmessung und kontinuierliche Herzratenvariabilität-Überwachung während des Schlafs
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Bewegungssensoren */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6 floating backdrop-blur-md bg-gradient-to-br from-violet-100/50 to-purple-100/50 border border-violet-200/30 dark:bg-gradient-to-br dark:from-violet-900/30 dark:to-purple-900/30 dark:border-violet-700/30"
|
||||
style={{animationDelay: '1.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-violet-500/20 rounded-full">
|
||||
<FaRunning className="text-violet-600 dark:text-violet-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center dreamy-text">
|
||||
Bewegungssensoren
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
6-Achsen-Bewegungssensor für Körperbewegungsanalyse und automatische Schlafphasenerkennung
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* KI-Algorithmen */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6 floating backdrop-blur-md bg-gradient-to-br from-emerald-100/50 to-teal-100/50 border border-emerald-200/30 dark:bg-gradient-to-br dark:from-emerald-900/30 dark:to-teal-900/30 dark:border-emerald-700/30"
|
||||
style={{animationDelay: '2s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-emerald-500/20 rounded-full">
|
||||
<FaChartBar className="text-emerald-600 dark:text-emerald-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center dreamy-text">
|
||||
KI-Algorithmen
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Fortschrittliche Algorithmen interpretieren Trauminhalte mit einer Genauigkeit von über 85%
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Adhäsiv-Technologie */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6 floating backdrop-blur-md bg-gradient-to-br from-amber-100/50 to-orange-100/50 border border-amber-200/30 dark:bg-gradient-to-br dark:from-amber-900/30 dark:to-orange-900/30 dark:border-amber-700/30"
|
||||
style={{animationDelay: '2.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-amber-500/20 rounded-full">
|
||||
<FaShieldAlt className="text-amber-600 dark:text-amber-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center dreamy-text">
|
||||
Adhäsiv-Technologie
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Biokompatible Materialien für hautfreundliche Haftung und schmerzfreie Entfernung
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Drahtlose Energieversorgung */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6 floating backdrop-blur-md bg-gradient-to-br from-rose-100/50 to-pink-100/50 border border-rose-200/30 dark:bg-gradient-to-br dark:from-rose-900/30 dark:to-pink-900/30 dark:border-rose-700/30"
|
||||
style={{animationDelay: '3s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-rose-500/20 rounded-full">
|
||||
<FaPlug className="text-rose-600 dark:text-rose-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center dreamy-text">
|
||||
Drahtlose Energieversorgung
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Thermoelektrische Generatoren nutzen Körperwärme für kontinuierlichen Betrieb ohne Batteriewechsel
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Technical Specifications Section */}
|
||||
<div
|
||||
className="dream-container floating mb-16 backdrop-blur-lg bg-gradient-to-br from-blue-500/30 to-purple-400/30 dark:from-blue-800/30 dark:to-purple-900/30 rounded-xl sm:rounded-2xl md:rounded-3xl p-6 sm:p-8 md:p-12"
|
||||
style={{animationDelay: '3.2s'}}>
|
||||
<div className="text-center">
|
||||
<FaMicrochip className="text-blue-500 dark:text-blue-400 mx-auto mb-4" size={32}/>
|
||||
<h2 className="dream-title text-2xl sm:text-3xl">Technische Spezifikationen</h2>
|
||||
<p className="text-base sm:text-lg mt-2 mb-6" style={{color: 'var(--text)'}}>
|
||||
Basierend auf aktueller Forschung
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6 sm:gap-8 mt-6 sm:mt-8">
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-purple-400 to-purple-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaBrain className="text-white" size={24}/>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">EEG-Sensormodul</h4>
|
||||
<ul className="text-xs sm:text-sm text-left list-disc pl-5" style={{color: 'var(--text)'}}>
|
||||
<li>Ultra-low-power Design mit nur 0,8 mW Verbrauch</li>
|
||||
<li>Drahtlose Datenübertragung via Bluetooth 5.0</li>
|
||||
<li>Miniaturisierte Bauweise: 9,2 Gramm Gesamtgewicht</li>
|
||||
<li>Bewegungsartefakt-Kompensation</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-blue-400 to-blue-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaHeartbeat className="text-white" size={24}/>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">Herzfrequenz-Monitoring</h4>
|
||||
<ul className="text-xs sm:text-sm text-left list-disc pl-5" style={{color: 'var(--text)'}}>
|
||||
<li>Photoplethysmographie (PPG) Technologie</li>
|
||||
<li>Kontinuierliche Herzratenvariabilität-Überwachung</li>
|
||||
<li>Mittlere absolute Abweichung unter 2 bpm</li>
|
||||
<li>Präzise Pulsmessung während des Schlafs</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-violet-400 to-violet-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaRunning className="text-white" size={24}/>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">Bewegungssensorik</h4>
|
||||
<ul className="text-xs sm:text-sm text-left list-disc pl-5" style={{color: 'var(--text)'}}>
|
||||
<li>6-Achsen-Bewegungssensor mit ±16 g Bereich</li>
|
||||
<li>Automatische Schlafphasenerkennung</li>
|
||||
<li>74,6% Genauigkeit bei Schlafstadienklassifizierung</li>
|
||||
<li>Bewegungsanalyse für präzise Traumdetektion</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Research Section */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-16">
|
||||
{/* KI-basierte Traumanalyse */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-6 sm:p-8 floating backdrop-blur-md bg-gradient-to-br from-indigo-100/50 to-blue-100/50 border border-indigo-200/30 dark:bg-gradient-to-br dark:from-indigo-900/30 dark:to-blue-900/30 dark:border-indigo-700/30"
|
||||
style={{animationDelay: '3.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-indigo-500/20 rounded-full">
|
||||
<FaFlask className="text-indigo-600 dark:text-indigo-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-3 sm:mb-4 text-center dreamy-text">
|
||||
Aktuelle Forschungsgrundlagen
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h4 className="font-semibold mb-2 text-sm sm:text-base">EEG-basierte Traumdetektion:</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Die neueste Forschung zeigt, dass EEG-Signale zur automatischen Traumdetektion mit über 85%
|
||||
Genauigkeit verwendet werden können.
|
||||
Eine 2025 veröffentlichte Studie demonstriert, dass bereits 8-10 EEG-Kanäle für eine
|
||||
effektive Traumerkennung ausreichen.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold mb-2 text-sm sm:text-base">Multimodale Traumanalyse:</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Das innovative DreamNet-Framework erreicht 99,0% Genauigkeit bei der Kombination von
|
||||
EEG-Daten mit physiologischen Signalen.
|
||||
Diese Technologie ermöglicht sowohl semantische als auch emotionale Traumanalyse mit 95,2%
|
||||
F1-Score.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* KI-Algorithmen */}
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-6 sm:p-8 floating backdrop-blur-md bg-gradient-to-br from-teal-100/50 to-green-100/50 border border-teal-200/30 dark:bg-gradient-to-br dark:from-teal-900/30 dark:to-green-900/30 dark:border-teal-700/30"
|
||||
style={{animationDelay: '4s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-teal-500/20 rounded-full">
|
||||
<FaBrain className="text-teal-600 dark:text-teal-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-3 sm:mb-4 text-center dreamy-text">
|
||||
KI-basierte Traumanalyse
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h4 className="font-semibold mb-2 text-sm sm:text-base">EEG-Musteranalyse:</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Forschungsergebnisse von 2025 zeigen, dass Common Spatial Patterns (CSP) mit k-nearest
|
||||
neighbors (KNN) die höchste Genauigkeit bei der Traumdetektion erreichen.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold mb-2 text-sm sm:text-base">Spektrale Traumanalyse:</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Aktuelle Studien belegen, dass Beta-Frequenzaktivität (15-30 Hz) während des REM-Schlafs als
|
||||
neuraler Fingerabdruck der Gedächtnisreaktivierung fungiert.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold mb-2 text-sm sm:text-base">Trauminhalt-Dekodierung:</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Das DreamNet-Framework verwendet Transformer-basierte Architektur mit multimodaler
|
||||
Aufmerksamkeit zur Dekodierung von Traumthemen und emotionalen Zuständen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Applications Section */}
|
||||
<div
|
||||
className="dream-container floating mb-16 backdrop-blur-lg bg-gradient-to-br from-green-500/30 to-teal-400/30 dark:from-green-800/30 dark:to-teal-900/30 rounded-xl sm:rounded-2xl md:rounded-3xl p-6 sm:p-8 md:p-12"
|
||||
style={{animationDelay: '4.2s'}}>
|
||||
<div className="text-center">
|
||||
<FaHeart className="text-green-500 dark:text-green-400 mx-auto mb-4" size={32}/>
|
||||
<h2 className="dream-title text-2xl sm:text-3xl">Anwendungsbereiche und Zielgruppen</h2>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-6 sm:gap-8 mt-6 sm:mt-8">
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-blue-400 to-blue-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaUserMd className="text-white" size={24}/>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">Medizinische
|
||||
Anwendungen</h4>
|
||||
<ul className="text-xs sm:text-sm text-left list-disc pl-5" style={{color: 'var(--text)'}}>
|
||||
<li>Schlafdiagnostik und Traumstörungsbehandlung</li>
|
||||
<li>Neurologische Forschung zu Bewusstseinszuständen</li>
|
||||
<li>Postoperative Überwachung in klinischen Umgebungen</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-teal-400 to-teal-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaUniversity className="text-white" size={24}/>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">Forschung und
|
||||
Entwicklung</h4>
|
||||
<ul className="text-xs sm:text-sm text-left list-disc pl-5" style={{color: 'var(--text)'}}>
|
||||
<li>Neurowissenschaftliche Studien zu Traummechanismen</li>
|
||||
<li>Brain-Computer-Interface Entwicklung</li>
|
||||
<li>Psychologische Forschung zu Unterbewusstsein</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-green-400 to-green-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaUsers className="text-white" size={24}/>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">Verbraucheranwendungen</h4>
|
||||
<ul className="text-xs sm:text-sm text-left list-disc pl-5" style={{color: 'var(--text)'}}>
|
||||
<li>Persönliche Schlafoptimierung und Traumtagebuch</li>
|
||||
<li>Wellness-Monitoring für bessere Schlafqualität</li>
|
||||
<li>Biofeedback-Systeme für Entspannung</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dreamy CTA Section */}
|
||||
<div className="relative mt-12 sm:mt-16">
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-6 sm:p-8 md:p-12 text-center floating bg-gradient-to-br from-pink-600 via-violet-600 to-purple-600 border-none overflow-hidden"
|
||||
style={{animationDelay: '4.5s'}}>
|
||||
<div className="relative z-10">
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-4 sm:mb-6">
|
||||
<FaMicrochip className="text-yellow-300 mb-2 sm:mb-0 sm:mr-3" size={24}/>
|
||||
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold text-white">Technische Vorteile</h2>
|
||||
<FaMicrochip className="text-yellow-300 mt-2 sm:mt-0 sm:ml-3 hidden sm:block" size={24}/>
|
||||
</div>
|
||||
<p className="text-base sm:text-lg md:text-xl text-purple-100 mb-6 sm:mb-8 md:mb-10 max-w-2xl mx-auto">
|
||||
Wissenschaftlich fundierte Sensorfusion, benutzerfreundliche Installation und maximaler
|
||||
Datenschutz
|
||||
in einem revolutionären Traumerfassungssystem
|
||||
</p>
|
||||
{/*<div className="flex justify-center w-full">*/}
|
||||
{/* <NavLink*/}
|
||||
{/* to='/'*/}
|
||||
{/* className="dreamy-button inline-flex items-center justify-center text-center mx-auto text-sm sm:text-base px-6 py-3 rounded-full font-medium shadow-lg"*/}
|
||||
{/* style={{minWidth: '200px'}}*/}
|
||||
{/* >*/}
|
||||
{/* <FaWifi className="mr-2 sm:mr-3" size={18}/>*/}
|
||||
{/* Mehr über die Technologie*/}
|
||||
{/* <HiSparkles className="ml-2 sm:ml-3" size={18}/>*/}
|
||||
{/* </NavLink>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>)
|
||||
}
|
@@ -5,6 +5,15 @@ import {mockDreams} from '../data/MockDreams';
|
||||
import MockUsers from '../data/MockUsers';
|
||||
import User from '../types/User';
|
||||
import type Dream from "../types/Dream.ts";
|
||||
import {formatDateNumeric, formatDateWithTime} from '../utils/DateUtils';
|
||||
import {lazy, Suspense} from 'react';
|
||||
|
||||
// Lazy load components
|
||||
const DreamVR = lazy(() => import('../components/DreamVR'));
|
||||
const SliderComponent = lazy(() => import('react-slick'));
|
||||
const EEGChart = lazy(() => import('../components/DreamCharts').then(module => ({default: module.EEGChart})));
|
||||
const VitalsChart = lazy(() => import('../components/DreamCharts').then(module => ({default: module.VitalsChart})));
|
||||
const MovementChart = lazy(() => import('../components/DreamCharts').then(module => ({default: module.MovementChart})));
|
||||
|
||||
export default function DreamPage() {
|
||||
const {id} = useParams<{ id: string }>();
|
||||
@@ -13,22 +22,23 @@ export default function DreamPage() {
|
||||
const dream: Dream | undefined = mockDreams.find(d => d.id === Number(id));
|
||||
const user: User | undefined = dream ? MockUsers.find(u => u.id === dream.userId) : undefined;
|
||||
|
||||
|
||||
if (!dream) {
|
||||
return (<div className="page p-4">
|
||||
<button
|
||||
onClick={() => navigate(-1)}
|
||||
className="mb-4 hover:underline"
|
||||
style={{ color: 'var(--accent)' }}
|
||||
style={{color: 'var(--accent)'}}
|
||||
>
|
||||
← Zurück
|
||||
</button>
|
||||
<p style={{ color: 'var(--text-muted)' }}>Traum nicht gefunden.</p>
|
||||
<p style={{color: 'var(--text-muted)'}}>Traum nicht gefunden.</p>
|
||||
</div>);
|
||||
}
|
||||
|
||||
return (<div className="page min-h-screen pb-20">
|
||||
{/* Header */}
|
||||
<div className="relative" style={{ background: 'var(--accent-gradient)' }}>
|
||||
<div className="relative" style={{background: 'var(--accent-gradient)'}}>
|
||||
<div className="p-4 sm:p-6 md:p-8 text-white">
|
||||
<button
|
||||
onClick={() => navigate(-1)}
|
||||
@@ -48,13 +58,7 @@ export default function DreamPage() {
|
||||
</h1>
|
||||
{user && (<p className="mt-1 text-white/80 text-sm sm:text-base">
|
||||
{user.name} •{' '}
|
||||
{dream.date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
{formatDateWithTime(dream.date)}
|
||||
</p>)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,20 +70,74 @@ export default function DreamPage() {
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">Traum-Beschreibung</span>
|
||||
</div>
|
||||
{(dream.input.inputType === 'image' || dream.input.inputType === 'audio') && (
|
||||
<div className="flex justify-center mb-1">
|
||||
{dream.input.inputType === 'audio' && (
|
||||
<audio></audio>
|
||||
)}
|
||||
{dream.input.inputType === 'image' && (
|
||||
<img alt={dream.input.imgAlt}></img>
|
||||
)}
|
||||
</div>)}
|
||||
<p className="leading-relaxed text-base sm:text-lg">
|
||||
{(dream.input.inputType === 'text' && dream.input.input)
|
||||
|| (dream.input.inputType === 'audio' && dream.input.transcript)
|
||||
|| (dream.input.inputType === 'image' && dream.input.description)}
|
||||
</p>
|
||||
|
||||
{dream.input.inputType === 'image' && (
|
||||
<div className="flex flex-col sm:flex-row gap-4 mb-4">
|
||||
<div className="sm:w-1/3">
|
||||
<img
|
||||
src={`/assets/dreams/images/${dream.input.img}`}
|
||||
alt={dream.input.imgAlt}
|
||||
className="w-full rounded-lg shadow-lg object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="sm:w-2/3">
|
||||
<p className="leading-relaxed text-base sm:text-lg">
|
||||
{dream.input.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{dream.input.inputType === 'audio' && (
|
||||
<div className="flex flex-col gap-4 mb-4">
|
||||
<div className="w-full">
|
||||
<audio
|
||||
controls
|
||||
src={`/assets/dreams/audio/${dream.input.audio}`}
|
||||
className="w-full"
|
||||
>
|
||||
Ihr Browser unterstützt das Audio-Element nicht.
|
||||
</audio>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<p className="leading-relaxed text-base sm:text-lg">
|
||||
{dream.input.transcript}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{dream.input.inputType === 'text' && (
|
||||
<p className="leading-relaxed text-base sm:text-lg">
|
||||
{dream.input.input}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{dream.input.inputType === 'chip' && (
|
||||
<div className="flex flex-col gap-4">
|
||||
<p className="leading-relaxed text-base sm:text-lg">
|
||||
{dream.input.text}
|
||||
</p>
|
||||
<Suspense fallback={<div
|
||||
className="w-full h-64 mt-4 border border-gray-200 rounded-lg p-2 flex justify-center items-center">
|
||||
<p>Lade EEG-Daten...</p>
|
||||
</div>}>
|
||||
<EEGChart chipInput={dream.input}/>
|
||||
</Suspense>
|
||||
<Suspense fallback={<div
|
||||
className="w-full h-64 mt-4 border border-gray-200 rounded-lg p-2 flex justify-center items-center">
|
||||
<p>Lade Vitaldaten...</p>
|
||||
</div>}>
|
||||
<VitalsChart chipInput={dream.input}/>
|
||||
</Suspense>
|
||||
<Suspense fallback={<div
|
||||
className="w-full h-64 mt-4 border border-gray-200 rounded-lg p-2 flex justify-center items-center">
|
||||
<p>Lade Bewegungsdaten...</p>
|
||||
</div>}>
|
||||
<MovementChart chipInput={dream.input}/>
|
||||
</Suspense>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{dream.ai?.interpretation && dream.ai.interpretation !== '' && (<div
|
||||
@@ -92,20 +150,85 @@ export default function DreamPage() {
|
||||
</p>
|
||||
</div>)}
|
||||
|
||||
{dream.ai?.image && dream.ai.image !== '' && (<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">KI-Bild</span>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<img
|
||||
src={`/assets/dreams/images/${dream.ai.image}`}
|
||||
alt="KI-generiertes Traumbild"
|
||||
className="max-w-full w-full rounded-lg shadow-lg object-contain mx-auto"
|
||||
style={{ maxHeight: '70vh' }}
|
||||
/>
|
||||
</div>
|
||||
</div>)}
|
||||
|
||||
{/* Carousel for KI-Bild and KI-Video if both exist */}
|
||||
{dream.ai?.image && dream.ai.video && dream.ai.image !== '' && dream.ai.video !== '' && (
|
||||
<div className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">KI-Medien</span>
|
||||
</div>
|
||||
<Suspense fallback={<div className="flex justify-center items-center h-[70vh]">
|
||||
<p>Lade Medien-Karussell...</p>
|
||||
</div>}>
|
||||
<SliderComponent
|
||||
dots={true}
|
||||
infinite={true}
|
||||
speed={500}
|
||||
slidesToShow={1}
|
||||
slidesToScroll={1}
|
||||
className="max-w-full mx-auto carousel-container"
|
||||
onInit={() => {
|
||||
import('slick-carousel/slick/slick.css');
|
||||
import('slick-carousel/slick/slick-theme.css');
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-center px-2">
|
||||
<img
|
||||
src={`/assets/dreams/images/${dream.ai.image}`}
|
||||
alt="KI-generiertes Traumbild"
|
||||
className="max-w-full w-full rounded-lg shadow-lg object-contain mx-auto"
|
||||
style={{maxHeight: '70vh'}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-center px-2">
|
||||
<video
|
||||
controls
|
||||
loop
|
||||
src={`/assets/dreams/videos/${dream.ai.video}`}
|
||||
className="max-w-full w-full rounded-lg shadow-lg object-contain mx-auto"
|
||||
style={{maxHeight: '70vh'}}
|
||||
>
|
||||
Ihr Browser unterstützt das Video-Element nicht.
|
||||
</video>
|
||||
</div>
|
||||
</SliderComponent>
|
||||
</Suspense>
|
||||
</div>)}
|
||||
|
||||
{/* Show KI-Bild alone if video doesn't exist */}
|
||||
{dream.ai?.image && dream.ai.image !== '' && (!dream.ai.video || dream.ai.video === '') && (
|
||||
<div className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">KI-Bild</span>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<img
|
||||
src={`/assets/dreams/images/${dream.ai.image}`}
|
||||
alt="KI-generiertes Traumbild"
|
||||
className="max-w-full w-full rounded-lg shadow-lg object-contain mx-auto"
|
||||
style={{maxHeight: '70vh'}}
|
||||
/>
|
||||
</div>
|
||||
</div>)}
|
||||
|
||||
{/* Show KI-Video alone if image doesn't exist */}
|
||||
{dream.ai?.video && dream.ai.video !== '' && (!dream.ai.image || dream.ai.image === '') && (
|
||||
<div className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">KI-Video</span>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<video
|
||||
controls
|
||||
loop
|
||||
src={`/assets/dreams/videos/${dream.ai.video}`}
|
||||
className="max-w-full w-full rounded-lg shadow-lg object-contain mx-auto"
|
||||
style={{maxHeight: '70vh'}}
|
||||
>
|
||||
Ihr Browser unterstützt das Video-Element nicht.
|
||||
</video>
|
||||
</div>
|
||||
</div>)}
|
||||
|
||||
{dream.ai?.audio && dream.ai.audio !== '' && (<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
@@ -113,8 +236,10 @@ export default function DreamPage() {
|
||||
<span className="font-medium dreamy-text">KI-Audio</span>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<audio
|
||||
controls
|
||||
<audio
|
||||
controls
|
||||
autoPlay
|
||||
loop
|
||||
src={`/assets/dreams/audio/${dream.ai.audio}`}
|
||||
className="w-full max-w-xs sm:max-w-md md:max-w-lg mx-auto"
|
||||
>
|
||||
@@ -123,26 +248,23 @@ export default function DreamPage() {
|
||||
</div>
|
||||
</div>)}
|
||||
|
||||
{dream.ai?.video && dream.ai.video !== '' && (<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">KI-Video</span>
|
||||
{/* VR Visualization */}
|
||||
{(dream.id === 10 || dream.input.inputType === 'chip') && (
|
||||
<div className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="font-medium dreamy-text">VR-Visualisierung</span>
|
||||
</div>
|
||||
<Suspense fallback={<div className="flex justify-center items-center h-[600px]">
|
||||
<p>Lade VR-Visualisierung...</p>
|
||||
</div>}>
|
||||
<DreamVR dream={dream} height="600px"/>
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<video
|
||||
controls
|
||||
src={`/assets/dreams/videos/${dream.ai.video}`}
|
||||
className="max-w-full w-full rounded-lg shadow-lg object-contain mx-auto"
|
||||
style={{ maxHeight: '70vh' }}
|
||||
>
|
||||
Ihr Browser unterstützt das Video-Element nicht.
|
||||
</video>
|
||||
</div>
|
||||
</div>)}
|
||||
)}
|
||||
|
||||
<div className="dreamy-card rounded-xl sm:rounded-2xl p-4 sm:p-6">
|
||||
<h2 className="text-lg font-semibold mb-3 dreamy-text">Details</h2>
|
||||
<div className="space-y-3" style={{ color: 'var(--text-muted)' }}>
|
||||
<div className="space-y-3" style={{color: 'var(--text-muted)'}}>
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between">
|
||||
<span className="font-medium mb-1 sm:mb-0">Eingabetyp</span>
|
||||
<span className="capitalize">{dream.input.inputType}</span>
|
||||
@@ -150,10 +272,23 @@ export default function DreamPage() {
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between">
|
||||
<span className="font-medium mb-1 sm:mb-0">Datum</span>
|
||||
<span>
|
||||
{dream.date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit', month: '2-digit', year: 'numeric',
|
||||
})}
|
||||
</span>
|
||||
{formatDateNumeric(dream.date)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between">
|
||||
<span className="font-medium mb-1 sm:mb-0">Tags</span>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{dream.tags.map((tag, index) => (
|
||||
<span key={index} className="px-2 py-1 text-xs rounded-full"
|
||||
style={{
|
||||
background: 'var(--accent-gradient)',
|
||||
color: 'white',
|
||||
boxShadow: '0 2px 5px var(--shadow)'
|
||||
}}>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -4,7 +4,7 @@ import Dream from '../types/Dream';
|
||||
import type User from "../types/User.ts";
|
||||
import {MockUserMap} from "../data/MockUsers.ts";
|
||||
import DreamCard from "../components/DreamCard";
|
||||
import {getSortedDreamsByDate} from "../data/DreamUtils";
|
||||
import {getSortedDreamsByDate} from "../utils/DreamUtils.ts";
|
||||
|
||||
export default function Feed() {
|
||||
const sortedDreams = getSortedDreamsByDate(mockDreams);
|
||||
|
@@ -1,255 +1,112 @@
|
||||
import {BsMoonStars, BsStars} from 'react-icons/bs';
|
||||
import {
|
||||
FaBed,
|
||||
FaBook,
|
||||
FaBrain,
|
||||
FaChartBar,
|
||||
FaCloud,
|
||||
FaEye,
|
||||
FaHeart,
|
||||
FaMicrophone,
|
||||
FaMoon,
|
||||
FaPen,
|
||||
FaRobot,
|
||||
FaStar,
|
||||
FaVrCardboard,
|
||||
} from 'react-icons/fa';
|
||||
import {HiSparkles} from 'react-icons/hi';
|
||||
import logotext from "../assets/logotext.svg";
|
||||
import {mockDreams} from '../data/MockDreams';
|
||||
import {MockUserMap} from '../data/MockUsers';
|
||||
import {getSortedDreamsByDate} from '../utils/DreamUtils.ts';
|
||||
import {getBackgroundStyle, getCardStyle, getTextStyle} from '../styles/StyleUtils';
|
||||
import {formatDateFull} from '../utils/DateUtils';
|
||||
import {NavLink} from 'react-router-dom';
|
||||
import {DreamCardCompact} from "../components/DreamCardCompact.tsx";
|
||||
import {DailyHighlights} from "../components/DailyHighlights.tsx";
|
||||
import {ChipCard} from "../components/ChipCard.tsx";
|
||||
|
||||
interface HomeProps {
|
||||
isLoggedIn: boolean;
|
||||
handleLogin: () => void;
|
||||
}
|
||||
|
||||
export default function Home({isLoggedIn, handleLogin}: HomeProps) {
|
||||
|
||||
if (isLoggedIn) {
|
||||
return (<div>
|
||||
<h1>Hallo Neo!</h1>
|
||||
</div>)
|
||||
}
|
||||
|
||||
return (<div className="p-4 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Floating Background Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<div className="absolute top-10 left-10 text-purple-200 opacity-30">
|
||||
<FaCloud size={40}/>
|
||||
</div>
|
||||
<div className="absolute top-32 right-20 text-purple-300 opacity-20">
|
||||
<BsStars size={30}/>
|
||||
</div>
|
||||
<div className="absolute bottom-40 left-32 text-purple-200 opacity-25">
|
||||
<BsMoonStars size={35}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div className="animate-pulse flex flex-col items-center mb-8 sm:mb-12">
|
||||
<div className="flex items-center justify-around">
|
||||
<img src={logotext} alt="REMind Logo and Text" className="h-32 sm:h-40 md:h-48 mb-4"/>
|
||||
</div>
|
||||
<p className="text-lg sm:text-xl dreamy-text">Träume analysieren, Gesellschaft verstehen</p>
|
||||
</div>
|
||||
<div className="dream-container max-w-3xl mx-auto backdrop-blur-sm bg-white/10 dark:bg-white/5 rounded-3xl p-4 sm:p-6 md:p-8">
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-3 sm:mb-4">
|
||||
<HiSparkles className="text-yellow-400 mb-2 sm:mb-0 sm:mr-2" size={20} />
|
||||
<h2 className="dream-title text-xl sm:text-2xl">Träume sammeln • KI verstehen • VR erleben</h2>
|
||||
<HiSparkles className="text-yellow-400 mt-2 sm:mt-0 sm:ml-2 hidden sm:block" size={20} />
|
||||
</div>
|
||||
<p className="mb-4 sm:mb-6 md:mb-8 text-sm sm:text-base md:text-lg" style={{color: 'var(--text)'}}>
|
||||
Verwandle deine nächtlichen Reisen in interaktive Traumlandschaften
|
||||
mit KI-gestützter Analyse und immersiven VR-Erlebnissen
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* Main Features Grid - Dreamy Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
{/* KI-Traumdeutung */}
|
||||
<div
|
||||
className="card floating backdrop-blur-md bg-gradient-to-br from-purple-100/50 to-pink-100/50 border border-purple-200/30 dark:bg-gradient-to-br dark:from-purple-900/30 dark:to-pink-900/30 dark:border-purple-700/30"
|
||||
style={{animationDelay: '0.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-purple-500/20 rounded-full">
|
||||
<FaBrain className="text-purple-600 dark:text-purple-400" size={28} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center" style={{color: 'var(--accent)'}}>
|
||||
KI-Traumdeutung
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Deine Träume werden von KI entschlüsselt -
|
||||
Symbole erkannt, Emotionen analysiert, Bedeutungen offenbart
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Multimediale Traumerfassung */}
|
||||
<div
|
||||
className="card floating backdrop-blur-md bg-gradient-to-br from-blue-100/50 to-indigo-100/50 border border-blue-200/30 dark:bg-gradient-to-br dark:from-blue-900/30 dark:to-indigo-900/30 dark:border-blue-700/30"
|
||||
style={{animationDelay: '1s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-blue-500/20 rounded-full">
|
||||
<FaMicrophone className="text-blue-600 dark:text-blue-400" size={28} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center" style={{color: 'var(--accent)'}}>
|
||||
Träume einfangen
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Sprich deine Träume in der Nacht, zeichne traumhafte Skizzen
|
||||
oder schreibe poetische Beschreibungen
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* VR-Traumwelten */}
|
||||
<div
|
||||
className="card floating backdrop-blur-md bg-gradient-to-br from-violet-100/50 to-purple-100/50 border border-violet-200/30 dark:bg-gradient-to-br dark:from-violet-900/30 dark:to-purple-900/30 dark:border-violet-700/30"
|
||||
style={{animationDelay: '1.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-violet-500/20 rounded-full">
|
||||
<FaVrCardboard className="text-violet-600 dark:text-violet-400" size={28} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center" style={{color: 'var(--accent)'}}>
|
||||
VR-Traumreisen
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Betritt deine Träume als begehbare Welten -
|
||||
schwebe durch Erinnerungen, berühre Traumsymbole
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Traumarchiv */}
|
||||
<div
|
||||
className="card backdrop-blur-md bg-gradient-to-br from-emerald-100/50 to-teal-100/50 border border-emerald-200/30 dark:bg-gradient-to-br dark:from-emerald-900/30 dark:to-teal-900/30 dark:border-emerald-700/30"
|
||||
style={{animationDelay: '2s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-emerald-500/20 rounded-full">
|
||||
<FaBook className="text-emerald-600 dark:text-emerald-400" size={28} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center" style={{color: 'var(--accent)'}}>
|
||||
Traumschatzkammer
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Deine Traumsammlung wächst - durchsuchbar nach Gefühlen,
|
||||
Symbolen und magischen Momenten
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Traumstatistiken */}
|
||||
<div
|
||||
className="card backdrop-blur-md bg-gradient-to-br from-amber-100/50 to-orange-100/50 border border-amber-200/30 dark:bg-gradient-to-br dark:from-amber-900/30 dark:to-orange-900/30 dark:border-amber-700/30"
|
||||
style={{animationDelay: '2.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-amber-500/20 rounded-full">
|
||||
<FaChartBar className="text-amber-600 dark:text-amber-400" size={28} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center" style={{color: 'var(--accent)'}}>
|
||||
Traummuster
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Entdecke die geheimen Muster deiner Nachtreisen -
|
||||
welche Träume kehren zurück?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Schlafrhythmus */}
|
||||
<div
|
||||
className="card backdrop-blur-md bg-gradient-to-br from-rose-100/50 to-pink-100/50 border border-rose-200/30 dark:bg-gradient-to-br dark:from-rose-900/30 dark:to-pink-900/30 dark:border-rose-700/30"
|
||||
style={{animationDelay: '3s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-3 sm:p-4 bg-rose-500/20 rounded-full">
|
||||
<FaMoon className="text-rose-600 dark:text-rose-400" size={28} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl font-bold mb-2 sm:mb-3 text-center" style={{color: 'var(--accent)'}}>
|
||||
Schlafzyklen
|
||||
</h3>
|
||||
<p className="text-center text-sm sm:text-base" style={{color: 'var(--text)'}}>
|
||||
Verstehe deine Schlafrhythmen und wie sie deine
|
||||
Traumlandschaften formen
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dreamy Workflow Section */}
|
||||
<div
|
||||
className="dream-container mb-16 backdrop-blur-lg bg-gradient-to-br from-pink-500/30 to-red-400/30 dark:from-pink-800/30 dark:to-red-900/30 rounded-3xl p-6 sm:p-8 md:p-12">
|
||||
<div className="text-center">
|
||||
<FaHeart className="text-pink-500 dark:text-pink-400 mx-auto mb-4" size={32} />
|
||||
<h2 className="dream-title text-2xl sm:text-3xl">Deine magische Traumreise</h2>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-6 sm:gap-8 mt-6 sm:mt-8">
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-purple-400 to-purple-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaBed className="text-white" size={24} />
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">1. Träumen</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
In der Nacht zeichnen deine Sensoren sanft deine Traumreisen auf
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-blue-400 to-blue-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaPen className="text-white" size={24} />
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">2. Einfangen</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Beim Erwachen flüsterst du deine Träume in die App
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-violet-400 to-violet-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaRobot className="text-white" size={24} />
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">3. Verzaubern</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
KI-Magie verwandelt deine Worte in Bilder, Klänge und Bedeutungen
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div
|
||||
className="bg-gradient-to-br from-pink-400 to-pink-600 rounded-full w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center mx-auto mb-4 sm:mb-6 shadow-lg">
|
||||
<FaEye className="text-white" size={24} />
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 sm:mb-3 dreamy-text text-base sm:text-lg">4. Erleben</h4>
|
||||
<p className="text-xs sm:text-sm" style={{color: 'var(--text)'}}>
|
||||
Tauche ein in deine VR-Traumwelten und entdecke dich selbst
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dreamy CTA Section */}
|
||||
<div className="relative mt-12 sm:mt-16">
|
||||
<div
|
||||
className="card p-6 sm:p-8 md:p-12 text-center bg-gradient-to-br from-pink-600 via-violet-600 to-purple-600 border-none overflow-hidden">
|
||||
<div className="relative z-10">
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-4 sm:mb-6">
|
||||
<FaStar className="text-yellow-300 mb-2 sm:mb-0 sm:mr-3" size={24} />
|
||||
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold text-white">Wo Träume Realität werden</h2>
|
||||
<FaStar className="text-yellow-300 mt-2 sm:mt-0 sm:ml-3 hidden sm:block" size={24} />
|
||||
</div>
|
||||
<p className="text-base sm:text-lg md:text-xl text-purple-100 mb-6 sm:mb-8 md:mb-10 max-w-2xl mx-auto">
|
||||
Lass dich von KI-gestützter Traumdeutung, VR-Erlebnissen und personalisierten
|
||||
Einsichten in eine tiefere Welt deines Unterbewusstseins führen
|
||||
</p>
|
||||
<button
|
||||
className="dreamy-button flex items-center mx-auto text-sm sm:text-base"
|
||||
onClick={handleLogin}
|
||||
>
|
||||
<FaMoon className="mr-2 sm:mr-3" size={18} />
|
||||
Lass die Magie beginnen!
|
||||
<HiSparkles className="ml-2 sm:ml-3" size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>)
|
||||
export default function Home() {
|
||||
const currentUser = MockUserMap.get(4); // Neo Quantum
|
||||
const currentDate = new Date();
|
||||
const formattedDate = formatDateFull(currentDate);
|
||||
|
||||
// Get personal dreams (latest 3 for user ID 4)
|
||||
const personalDreams = getSortedDreamsByDate(
|
||||
mockDreams.filter(dream => dream.userId === 4)
|
||||
).slice(0, 3);
|
||||
|
||||
// Get friends' dreams (latest 5 from other users)
|
||||
const friendsDreams = getSortedDreamsByDate(
|
||||
mockDreams.filter(dream => dream.userId !== 4)
|
||||
).slice(0, 5);
|
||||
|
||||
return (
|
||||
<div className="page p-4 space-y-6">
|
||||
{/* Welcome Card */}
|
||||
<div className={getCardStyle().className}
|
||||
style={getCardStyle()}>
|
||||
<h1 className="text-2xl font-bold mb-2 dream-title">Hallo Neo!</h1>
|
||||
<p className="text-sm" style={getTextStyle('muted')}>{formattedDate}</p>
|
||||
<p className="mt-2" style={getTextStyle()}>Willkommen zurück in deiner Traumwelt.</p>
|
||||
</div>
|
||||
|
||||
{/* Streak Notification */}
|
||||
<div
|
||||
className={getCardStyle(true).className}
|
||||
style={getBackgroundStyle('accent-gradient')}>
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-8 w-8" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M13 10V3L4 14h7v7l9-11h-7z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<h3 className="font-bold">Traum-Streak: {currentUser?.streakDays} Tage</h3>
|
||||
<p className="text-sm">Beeindruckend! Du hältst deine Traum-Aufzeichnungen konstant bei.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/*<DreamRecord/>*/}
|
||||
|
||||
{/* Personal Feed */}
|
||||
<NavLink to='/feed'
|
||||
className="block mb-4 transition-all duration-300 hover:transform hover:scale-[1.01] bg-gradient-to-br from-[rgba(166,77,255,0.35)] to-[rgba(213,0,249,0.35)] backdrop-blur-md rounded-xl shadow-lg dreamy-card">
|
||||
<div className="p-4">
|
||||
<h3 className="font-bold mb-2 dream-title text-base">Deine letzten Träume</h3>
|
||||
{personalDreams.length > 0 ? (
|
||||
<div className="space-y-2">
|
||||
{personalDreams.map((dream, index) => (
|
||||
<DreamCardCompact
|
||||
key={dream.id}
|
||||
dream={dream}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-[var(--text-muted)]">
|
||||
Du hast noch keine Träume aufgezeichnet. Starte jetzt!
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* Friends Feed */}
|
||||
<NavLink to='/feed'
|
||||
className="block mb-4 transition-all duration-300 hover:transform hover:scale-[1.01] bg-gradient-to-br from-[rgba(166,77,255,0.35)] to-[rgba(213,0,249,0.35)] backdrop-blur-md rounded-xl shadow-lg dreamy-card">
|
||||
<div className="p-4">
|
||||
<h3 className="font-bold mb-2 dream-title text-base">Träume von Freunden</h3>
|
||||
<div className="space-y-2">
|
||||
{friendsDreams.map((dream, index) => {
|
||||
const dreamUser = MockUserMap.get(dream.userId);
|
||||
return (
|
||||
<DreamCardCompact
|
||||
key={dream.id}
|
||||
dream={dream}
|
||||
index={index}
|
||||
showUser={true}
|
||||
user={dreamUser}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* Daily Highlights */}
|
||||
<NavLink to='/dreamarchive/user-dreams'>
|
||||
<DailyHighlights/>
|
||||
</NavLink>
|
||||
|
||||
{/* Ad Banner */}
|
||||
<ChipCard/>
|
||||
</div>
|
||||
)
|
||||
;
|
||||
}
|
||||
|
@@ -15,10 +15,39 @@ import {
|
||||
FaVrCardboard,
|
||||
} from 'react-icons/fa';
|
||||
import {HiSparkles} from 'react-icons/hi';
|
||||
import logotext from "../assets/logotext.svg";
|
||||
import {NavLink} from 'react-router-dom';
|
||||
import {useEffect, useState} from 'react';
|
||||
import logotext from '../assets/logotext.svg'
|
||||
import logotext_dark from '../assets/logotext_dark.svg'
|
||||
|
||||
export default function Overview() {
|
||||
const [isDarkTheme, setIsDarkTheme] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Initialize theme state
|
||||
const updateThemeState = () => {
|
||||
const theme = document.documentElement.getAttribute('data-theme');
|
||||
setIsDarkTheme(theme === 'dark');
|
||||
};
|
||||
|
||||
// Set initial state
|
||||
updateThemeState();
|
||||
|
||||
// Create observer to watch for theme changes
|
||||
const observer = new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.attributeName === 'data-theme') {
|
||||
updateThemeState();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start observing
|
||||
observer.observe(document.documentElement, {attributes: true});
|
||||
|
||||
// Cleanup
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Floating Background Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
@@ -37,7 +66,11 @@ export default function Overview() {
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div className="animate-pulse flex flex-col items-center mb-8 sm:mb-12">
|
||||
<div className="flex items-center justify-around">
|
||||
<img src={logotext} alt="REMind Logo and Text" className="h-32 sm:h-40 md:h-48 mb-4"/>
|
||||
{isDarkTheme ? (
|
||||
<img src={logotext} alt="REMind Logo and Text" className="h-32 sm:h-40 md:h-48 mb-4"/>
|
||||
) : (
|
||||
<img src={logotext_dark} alt="REMind Logo and Text" className="h-32 sm:h-40 md:h-48 mb-4"/>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-lg sm:text-xl dreamy-text">Träume analysieren, Gesellschaft verstehen</p>
|
||||
</div>
|
||||
@@ -55,7 +88,8 @@ export default function Overview() {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* Main Features Grid - Dreamy Cards */}
|
||||
{/* Main Features Grid - Dreamy Cards */
|
||||
}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
{/* KI-Traumdeutung */}
|
||||
<div
|
||||
@@ -166,7 +200,8 @@ export default function Overview() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dreamy Workflow Section */}
|
||||
{/* Dreamy Workflow Section */
|
||||
}
|
||||
<div
|
||||
className="dream-container floating mb-16 backdrop-blur-lg bg-gradient-to-br from-pink-500/30 to-red-400/30 dark:from-pink-800/30 dark:to-red-900/30 rounded-xl sm:rounded-2xl md:rounded-3xl p-6 sm:p-8 md:p-12"
|
||||
style={{animationDelay: '3.2s'}}>
|
||||
@@ -218,7 +253,8 @@ export default function Overview() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dreamy CTA Section */}
|
||||
{/* Dreamy CTA Section */
|
||||
}
|
||||
<div className="relative mt-12 sm:mt-16">
|
||||
<div
|
||||
className="dreamy-card rounded-xl sm:rounded-2xl p-6 sm:p-8 md:p-12 text-center floating bg-gradient-to-br from-pink-600 via-violet-600 to-purple-600 border-none overflow-hidden"
|
||||
|
@@ -13,57 +13,60 @@ const ProfilePage: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="page p-4 pb-20">
|
||||
{/* Profile Card */}
|
||||
<div
|
||||
className="dreamy-border rounded-xl p-6 max-w-md mx-auto overflow-hidden"
|
||||
className="dreamy-border rounded-xl p-6 max-w-md mx-auto overflow-hidden mb-10"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.25), rgba(213, 0, 249, 0.25))',
|
||||
backdropFilter: 'blur(10px)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.2)'
|
||||
}}>
|
||||
{/* Profile Picture */}
|
||||
{/* Profile Picture */}
|
||||
<div className="w-28 h-28 sm:w-36 sm:h-36 rounded-full overflow-hidden mb-6 mx-auto relative"
|
||||
style={{
|
||||
background: 'var(--accent-gradient)',
|
||||
padding: '4px',
|
||||
boxShadow: '0 0 15px var(--shadow)'
|
||||
}}>
|
||||
<img
|
||||
src={profileUser ? `/assets/profiles/${profileUser.profilePicture}` : `https://ui-avatars.com/api/?name=${defaultName}&background=random&color=fff&size=128`}
|
||||
alt={profileUser ? profileUser.name : defaultName}
|
||||
className="w-full h-full object-cover rounded-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* User Information */}
|
||||
<div className="text-center w-full">
|
||||
<h2 className="text-xl sm:text-2xl mb-2 break-words dreamy-text font-bold">{profileUser ? profileUser.name : defaultName}</h2>
|
||||
<p className="text-text-muted mb-8 break-words">{profileUser ? profileUser.email : defaultEmail}</p>
|
||||
|
||||
<div className="grid grid-cols-2 gap-6 mt-6 text-center">
|
||||
<div
|
||||
className="dreamy-border rounded-lg p-4"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35))',
|
||||
boxShadow: '0 0 15px var(--shadow)',
|
||||
backdropFilter: 'blur(5px)'
|
||||
}}
|
||||
>
|
||||
<p className="dreamy-text text-2xl sm:text-3xl font-bold">{profileUser ? profileUser.dreamCount : defaultDreamCount}</p>
|
||||
<p className="text-sm sm:text-base font-medium" style={{color: 'var(--text)'}}>Dreams</p>
|
||||
<img
|
||||
src={profileUser ? `/assets/profiles/${profileUser.profilePicture}` : `https://ui-avatars.com/api/?name=${defaultName}&background=random&color=fff&size=128`}
|
||||
alt={profileUser ? profileUser.name : defaultName}
|
||||
className="w-full h-full object-cover rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="dreamy-border rounded-lg p-4"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35))',
|
||||
boxShadow: '0 0 15px var(--shadow)',
|
||||
backdropFilter: 'blur(5px)'
|
||||
}}
|
||||
>
|
||||
<p className="dreamy-text text-2xl sm:text-3xl font-bold">{profileUser ? profileUser.streakDays : defaultStreakDays}</p>
|
||||
<p className="text-sm sm:text-base font-medium" style={{color: 'var(--text)'}}>Days Streak</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* User Information */}
|
||||
<div className="text-center w-full">
|
||||
<h2 className="text-xl sm:text-2xl mb-2 break-words dreamy-text font-bold">{profileUser ? profileUser.name : defaultName}</h2>
|
||||
<p className="text-text-muted mb-8 break-words">{profileUser ? profileUser.email : defaultEmail}</p>
|
||||
|
||||
<div className="grid grid-cols-2 gap-6 mt-6 text-center">
|
||||
<div
|
||||
className="dreamy-border rounded-lg p-4"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35))',
|
||||
boxShadow: '0 0 15px var(--shadow)',
|
||||
backdropFilter: 'blur(5px)'
|
||||
}}
|
||||
>
|
||||
<p className="dreamy-text text-2xl sm:text-3xl font-bold">{profileUser ? profileUser.dreamCount : defaultDreamCount}</p>
|
||||
<p className="text-sm sm:text-base font-medium" style={{color: 'var(--text)'}}>Dreams</p>
|
||||
</div>
|
||||
<div
|
||||
className="dreamy-border rounded-lg p-4"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35))',
|
||||
boxShadow: '0 0 15px var(--shadow)',
|
||||
backdropFilter: 'blur(5px)'
|
||||
}}
|
||||
>
|
||||
<p className="dreamy-text text-2xl sm:text-3xl font-bold">{profileUser ? profileUser.streakDays : defaultStreakDays}</p>
|
||||
<p className="text-sm sm:text-base font-medium" style={{color: 'var(--text)'}}>Days Streak</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Account Settings (moved back into profile card) */}
|
||||
<div className="mt-10">
|
||||
<h3 className="dreamy-text text-lg mb-4 font-bold">Account Settings</h3>
|
||||
<div
|
||||
@@ -84,8 +87,8 @@ const ProfilePage: React.FC = () => {
|
||||
opacity: '0.9',
|
||||
boxShadow: 'inset 0 0 5px rgba(166, 77, 255, 0.5)'
|
||||
}}></span>
|
||||
</label>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex justify-between items-center py-3 flex-wrap">
|
||||
<span className="mr-2 font-medium" style={{color: 'var(--text)'}}>Privacy</span>
|
||||
<label className="relative inline-block w-12 h-6">
|
||||
@@ -96,14 +99,58 @@ const ProfilePage: React.FC = () => {
|
||||
opacity: '0.9',
|
||||
boxShadow: 'inset 0 0 5px rgba(166, 77, 255, 0.5)'
|
||||
}}></span>
|
||||
</label>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Project Information Card */}
|
||||
<div
|
||||
className="dreamy-border rounded-xl p-6 max-w-md mx-auto overflow-hidden"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.25), rgba(213, 0, 249, 0.25))',
|
||||
backdropFilter: 'blur(10px)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.2)'
|
||||
}}>
|
||||
<h3 className="dreamy-text text-lg mb-4 font-bold text-center">Project Information</h3>
|
||||
<div
|
||||
className="dreamy-border rounded-lg p-5 text-left"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.35), rgba(213, 0, 249, 0.35))',
|
||||
boxShadow: '0 0 15px var(--shadow)',
|
||||
backdropFilter: 'blur(5px)'
|
||||
}}
|
||||
>
|
||||
<div className="py-2 border-b border-purple-100/30">
|
||||
<p className="font-medium mb-1" style={{color: 'var(--text)'}}>Gitea Link:</p>
|
||||
<a
|
||||
href="https://gitea.puchstein.bayern/mpuchstein/REMind"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm break-words hover:underline"
|
||||
style={{color: 'var(--accent)'}}
|
||||
>
|
||||
https://gitea.puchstein.bayern/mpuchstein/REMind
|
||||
</a>
|
||||
</div>
|
||||
<div className="py-2 border-b border-purple-100/30">
|
||||
<p className="font-medium mb-1" style={{color: 'var(--text)'}}>Gruppenmitglieder:</p>
|
||||
<p className="text-sm">Kim Anhäuser, Matthias Puchstein, Anya Zell</p>
|
||||
</div>
|
||||
<div className="py-2 border-b border-purple-100/30">
|
||||
<p className="font-medium mb-1" style={{color: 'var(--text)'}}>Modul:</p>
|
||||
<p className="text-sm">Einführung in die Text und Medienanalyse bei Prof. Dr. Rettiner und Dr. phil.
|
||||
Ripoll</p>
|
||||
</div>
|
||||
<div className="py-2">
|
||||
<p className="font-medium mb-1" style={{color: 'var(--text)'}}>Genutzte AI:</p>
|
||||
<p className="text-sm">Perplexity, Junie, Veo, Imgen, Suno</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfilePage;
|
||||
export default ProfilePage;
|
291
src/pages/dreamarchive/CulturalLandscapes.tsx
Normal file
291
src/pages/dreamarchive/CulturalLandscapes.tsx
Normal file
@@ -0,0 +1,291 @@
|
||||
import {getBackgroundStyle, getTextStyle} from '../../styles/StyleUtils';
|
||||
import {FaGlobeAfrica, FaGlobeAsia, FaGlobeEurope, FaHandshake} from 'react-icons/fa';
|
||||
|
||||
export default function CulturalLandscapes() {
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div className="animate-pulse flex flex-col items-center mb-8 sm:mb-12">
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4 dream-title">Kulturelle
|
||||
Traumlandschaften</h1>
|
||||
<p className="text-lg sm:text-xl dreamy-text">Traumcharakteristika verschiedener Kulturen und
|
||||
Gesellschaften</p>
|
||||
</div>
|
||||
<div
|
||||
className="dream-container floating max-w-3xl mx-auto backdrop-blur-sm bg-white/10 dark:bg-white/5 rounded-3xl p-4 sm:p-6 md:p-8"
|
||||
style={{animationDelay: '0.2s'}}>
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-3 sm:mb-4">
|
||||
<h2 className="dream-title text-xl sm:text-2xl">Kulturelle Unterschiede im Traumerleben</h2>
|
||||
</div>
|
||||
<p className="mb-4 sm:mb-6 md:mb-8 text-sm sm:text-base md:text-lg" style={{color: 'var(--text)'}}>
|
||||
Entdecke, wie kulturelle Hintergründe und gesellschaftliche Strukturen die Traumthemen,
|
||||
-emotionen und -narrative beeinflussen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Research Highlight */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Forschung von David Samson (University of
|
||||
Toronto)</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* BaYaka */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('violet')}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-violet-500/20 rounded-full">
|
||||
<FaGlobeAfrica className="text-violet-600 dark:text-violet-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">BaYaka</h3>
|
||||
<p className="text-sm mb-2 text-center">(Demokratische Republik Kongo)</p>
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Traumstruktur</h4>
|
||||
<p className="text-sm">Träume beginnen mit Bedrohungen, enden mit Gemeinschaftsrettung</p>
|
||||
</div>
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Die BaYaka-Gemeinschaft zeigt ein einzigartiges Muster: Ihre Träume beginnen oft mit
|
||||
persönlichen Bedrohungen, entwickeln sich aber zu Szenarien, in denen die Gemeinschaft
|
||||
zusammenkommt, um das Problem zu lösen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Hadza */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('amber')}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-amber-500/20 rounded-full">
|
||||
<FaHandshake className="text-amber-600 dark:text-amber-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">Hadza</h3>
|
||||
<p className="text-sm mb-2 text-center">(Tansania)</p>
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Traumstruktur</h4>
|
||||
<p className="text-sm">Starke soziale Bindungen reflektieren sich in kooperativen
|
||||
Traumlösungen</p>
|
||||
</div>
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Die Hadza-Gemeinschaft, bekannt für ihre egalitäre Sozialstruktur, zeigt in ihren Träumen
|
||||
häufig Szenarien, in denen Probleme durch Zusammenarbeit und gegenseitige Unterstützung
|
||||
gelöst werden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Western Societies */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('blue')}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-blue-500/20 rounded-full">
|
||||
<FaGlobeEurope className="text-blue-600 dark:text-blue-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">Westliche Gesellschaften</h3>
|
||||
<p className="text-sm mb-2 text-center">(Europa & Nordamerika)</p>
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Traumstruktur</h4>
|
||||
<p className="text-sm">Fokus auf individuellen Stress, weniger soziale Unterstützung</p>
|
||||
</div>
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Im Gegensatz zu indigenen Gemeinschaften zeigen Träume in westlichen Gesellschaften oft
|
||||
einen Fokus auf individuelle Probleme und Lösungen, mit weniger Betonung auf
|
||||
gemeinschaftlicher Unterstützung.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Regional Dream Characteristics */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Regionale Traumcharakteristika</h2>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
||||
{/* Northern Europe */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('blue')}>
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-4 bg-blue-500/20 rounded-full mr-4">
|
||||
<FaGlobeEurope className="text-blue-600 dark:text-blue-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold dreamy-text">Nordeuropa</h3>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="relative h-6 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div className="absolute top-0 left-0 h-full bg-blue-500 dark:bg-blue-600 rounded-full"
|
||||
style={{width: '67%'}}></div>
|
||||
<div
|
||||
className="absolute top-0 left-0 w-full h-full flex items-center justify-center text-xs font-bold">
|
||||
67% Träume über Isolation und Dunkelheit
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs mt-1 text-right" style={getTextStyle('muted')}>Saisonale Effekte
|
||||
deutlich erkennbar</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
In nordeuropäischen Ländern zeigt sich ein deutlicher Einfluss der langen, dunklen Winter
|
||||
auf die Traumthemen. Isolation und Dunkelheit dominieren, besonders während der
|
||||
Wintermonate.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Mediterranean */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('amber')}>
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-4 bg-amber-500/20 rounded-full mr-4">
|
||||
<FaGlobeEurope className="text-amber-600 dark:text-amber-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold dreamy-text">Mittelmeerraum</h3>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<div
|
||||
className="relative h-6 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-amber-500 dark:bg-amber-600 rounded-full"
|
||||
style={{width: '58%'}}></div>
|
||||
<div
|
||||
className="absolute top-0 left-0 w-full h-full flex items-center justify-center text-xs font-bold">
|
||||
58% Soziale Träume
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="relative h-6 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-amber-500 dark:bg-amber-600 rounded-full"
|
||||
style={{width: '42%'}}></div>
|
||||
<div
|
||||
className="absolute top-0 left-0 w-full h-full flex items-center justify-center text-xs font-bold">
|
||||
42% Familienthemen
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Im Mittelmeerraum spiegeln Träume die starke soziale und familiäre Orientierung der Kultur
|
||||
wider. Gemeinschaftliche Aktivitäten und Familientreffen sind häufige Traumthemen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* East Asia */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('emerald')}>
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-4 bg-emerald-500/20 rounded-full mr-4">
|
||||
<FaGlobeAsia className="text-emerald-600 dark:text-emerald-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold dreamy-text">Ostasien</h3>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="relative h-6 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-emerald-500 dark:bg-emerald-600 rounded-full"
|
||||
style={{width: '71%'}}></div>
|
||||
<div
|
||||
className="absolute top-0 left-0 w-full h-full flex items-center justify-center text-xs font-bold">
|
||||
71% Träume über Leistung und gesellschaftliche Erwartungen
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
In ostasiatischen Kulturen reflektieren Träume häufig den gesellschaftlichen Druck und
|
||||
Leistungserwartungen. Prüfungssituationen, beruflicher Erfolg und soziale Anerkennung sind
|
||||
wiederkehrende Themen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Sub-Saharan Africa */}
|
||||
<div className="dreamy-card rounded-xl p-6 h-full flex flex-col" style={getBackgroundStyle('purple')}>
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-4 bg-purple-500/20 rounded-full mr-4">
|
||||
<FaGlobeAfrica className="text-purple-600 dark:text-purple-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold dreamy-text">Afrika (Subsahara)</h3>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="relative h-6 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-purple-500 dark:bg-purple-600 rounded-full"
|
||||
style={{width: '84%'}}></div>
|
||||
<div
|
||||
className="absolute top-0 left-0 w-full h-full flex items-center justify-center text-xs font-bold">
|
||||
84% Träume mit Gemeinschaftsunterstützung
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
In vielen subsaharischen Kulturen zeigen Träume eine starke Betonung von Gemeinschaft und
|
||||
gegenseitiger Unterstützung. Traumlösungen beinhalten fast immer die Hilfe von
|
||||
Familienmitgliedern oder der Gemeinschaft.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Cultural Comparison */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Kultureller Vergleich: Traumthemen</h2>
|
||||
|
||||
<div className="dreamy-card rounded-xl p-6" style={getBackgroundStyle('rose')}>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-left p-2">Traumthema</th>
|
||||
<th className="text-center p-2">Westliche Gesellschaften</th>
|
||||
<th className="text-center p-2">Ostasien</th>
|
||||
<th className="text-center p-2">Indigene Gemeinschaften</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="bg-white/10 dark:bg-black/10">
|
||||
<td className="p-2 font-bold">Angstträume</td>
|
||||
<td className="text-center p-2">Persönliches Versagen, Verlust</td>
|
||||
<td className="text-center p-2">Soziale Ablehnung, Scham</td>
|
||||
<td className="text-center p-2">Naturgefahren, Ressourcenmangel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="p-2 font-bold">Soziale Träume</td>
|
||||
<td className="text-center p-2">Fokus auf enge Freunde, Partner</td>
|
||||
<td className="text-center p-2">Familiäre Hierarchie, Respekt</td>
|
||||
<td className="text-center p-2">Gesamte Gemeinschaft, Ahnen</td>
|
||||
</tr>
|
||||
<tr className="bg-white/10 dark:bg-black/10">
|
||||
<td className="p-2 font-bold">Erfolgsträume</td>
|
||||
<td className="text-center p-2">Individuelle Leistung, Anerkennung</td>
|
||||
<td className="text-center p-2">Familienstolz, Gruppenleistung</td>
|
||||
<td className="text-center p-2">Gemeinschaftlicher Erfolg, Teilen</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="p-2 font-bold">Spirituelle Träume</td>
|
||||
<td className="text-center p-2">Selten, abstrakt</td>
|
||||
<td className="text-center p-2">Ahnenverehrung, Harmonie</td>
|
||||
<td className="text-center p-2">Häufig, konkrete Führung</td>
|
||||
</tr>
|
||||
<tr className="bg-white/10 dark:bg-black/10">
|
||||
<td className="p-2 font-bold">Problemlösung</td>
|
||||
<td className="text-center p-2">Individuell, technologisch</td>
|
||||
<td className="text-center p-2">Hierarchisch, kollektiv</td>
|
||||
<td className="text-center p-2">Gemeinschaftlich, naturbezogen</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p className="text-sm mt-4" style={getTextStyle('normal')}>
|
||||
Diese Tabelle zeigt die kulturellen Unterschiede in der Ausprägung verschiedener Traumthemen.
|
||||
Während westliche Gesellschaften einen stärkeren Fokus auf individuelle Aspekte legen, betonen
|
||||
ostasiatische und indigene Kulturen stärker gemeinschaftliche und kollektive Elemente.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
141
src/pages/dreamarchive/DreamArchiveIndex.tsx
Normal file
141
src/pages/dreamarchive/DreamArchiveIndex.tsx
Normal file
@@ -0,0 +1,141 @@
|
||||
import {NavLink} from 'react-router-dom';
|
||||
import {FaFlask, FaGlobeEurope, FaHome, FaMicrochip, FaUser, FaUsers} from 'react-icons/fa';
|
||||
import {getBackgroundStyle, getTextStyle} from '../../styles/StyleUtils';
|
||||
|
||||
export default function DreamArchiveIndex() {
|
||||
return (
|
||||
<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div
|
||||
className="dream-container floating max-w-3xl mx-auto backdrop-blur-sm bg-white/10 dark:bg-white/5 rounded-3xl p-4 sm:p-6 md:p-8"
|
||||
style={{animationDelay: '0.2s'}}>
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-3 sm:mb-4">
|
||||
<h2 className="dream-title text-xl sm:text-2xl">Entdecke die Welt der Träume</h2>
|
||||
</div>
|
||||
<p className="mb-4 sm:mb-6 md:mb-8 text-sm sm:text-base md:text-lg" style={{color: 'var(--text)'}}>
|
||||
Erkunde die Zusammenhänge zwischen weltweiten Ereignissen und Traummustern, kulturelle
|
||||
Unterschiede und technologische Fortschritte in der Traumforschung.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Archive Pages Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
{/* Worldwide Events */}
|
||||
<NavLink to="/dreamarchive/worldwide-events" className="no-underline h-full">
|
||||
<div
|
||||
className="dreamy-card rounded-xl p-6 floating h-full flex flex-col"
|
||||
style={{...getBackgroundStyle('purple'), animationDelay: '0.5s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-purple-500/20 rounded-full">
|
||||
<FaGlobeEurope className="text-purple-600 dark:text-purple-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">
|
||||
Weltweite Ereignisse
|
||||
</h3>
|
||||
<p className="text-center text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Erforsche die Korrelation zwischen globalen Ereignissen und Traumreaktionen
|
||||
</p>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* Cultural Landscapes */}
|
||||
<NavLink to="/dreamarchive/cultural-landscapes" className="no-underline h-full">
|
||||
<div
|
||||
className="dreamy-card rounded-xl p-6 floating h-full flex flex-col"
|
||||
style={{...getBackgroundStyle('blue'), animationDelay: '0.6s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-blue-500/20 rounded-full">
|
||||
<FaUsers className="text-blue-600 dark:text-blue-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">
|
||||
Kulturelle Traumlandschaften
|
||||
</h3>
|
||||
<p className="text-center text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Vergleiche Traumcharakteristika verschiedener Kulturen und Regionen
|
||||
</p>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* Living Conditions */}
|
||||
<NavLink to="/dreamarchive/living-conditions" className="no-underline h-full">
|
||||
<div
|
||||
className="dreamy-card rounded-xl p-6 floating h-full flex flex-col"
|
||||
style={{...getBackgroundStyle('emerald'), animationDelay: '0.7s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-emerald-500/20 rounded-full">
|
||||
<FaHome className="text-emerald-600 dark:text-emerald-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">
|
||||
Lebensbedingungen & Traumqualität
|
||||
</h3>
|
||||
<p className="text-center text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Entdecke wie sozioökonomische und Umweltfaktoren Träume beeinflussen
|
||||
</p>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* Technology */}
|
||||
<NavLink to="/dreamarchive/technology" className="no-underline h-full">
|
||||
<div
|
||||
className="dreamy-card rounded-xl p-6 floating h-full flex flex-col"
|
||||
style={{...getBackgroundStyle('amber'), animationDelay: '0.8s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-amber-500/20 rounded-full">
|
||||
<FaMicrochip className="text-amber-600 dark:text-amber-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">
|
||||
Technologie & Traumforschung
|
||||
</h3>
|
||||
<p className="text-center text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Erfahre mehr über neueste Entwicklungen in der Traumforschungstechnologie
|
||||
</p>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* User Dreams */}
|
||||
<NavLink to="/dreamarchive/user-dreams" className="no-underline h-full">
|
||||
<div
|
||||
className="dreamy-card rounded-xl p-6 floating h-full flex flex-col"
|
||||
style={{...getBackgroundStyle('rose'), animationDelay: '0.9s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-rose-500/20 rounded-full">
|
||||
<FaUser className="text-rose-600 dark:text-rose-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">
|
||||
Deine Träume im Kontext
|
||||
</h3>
|
||||
<p className="text-center text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Sieh wie deine Träume im Vergleich zur globalen Traumdatenbank stehen
|
||||
</p>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
{/* Research Live */}
|
||||
<NavLink to="/dreamarchive/research-live" className="no-underline h-full">
|
||||
<div
|
||||
className="dreamy-card rounded-xl p-6 floating h-full flex flex-col"
|
||||
style={{...getBackgroundStyle('violet'), animationDelay: '1.0s'}}>
|
||||
<div className="flex justify-center mb-4">
|
||||
<div className="p-4 bg-violet-500/20 rounded-full">
|
||||
<FaFlask className="text-violet-600 dark:text-violet-400" size={28}/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">
|
||||
Traumforschung Live
|
||||
</h3>
|
||||
<p className="text-center text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Aktuelle Studien, Citizen Science und Interviews mit Forschern
|
||||
</p>
|
||||
</div>
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
331
src/pages/dreamarchive/LivingConditions.tsx
Normal file
331
src/pages/dreamarchive/LivingConditions.tsx
Normal file
@@ -0,0 +1,331 @@
|
||||
import {FaCity, FaGraduationCap, FaLightbulb, FaMoneyBillWave, FaSmog, FaVolumeUp} from 'react-icons/fa';
|
||||
import HeroSection from '../../components/dreamarchive/HeroSection';
|
||||
import SectionHeader from '../../components/dreamarchive/SectionHeader';
|
||||
import DreamyCard from '../../components/dreamarchive/DreamyCard';
|
||||
import IconWithBackground from '../../components/dreamarchive/IconWithBackground';
|
||||
|
||||
export default function LivingConditions() {
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<HeroSection
|
||||
containerTitle="Wie unsere Umgebung unsere Träume formt"
|
||||
description="Entdecke, wie sozioökonomische Faktoren und Umweltbedingungen die Qualität, Intensität und Inhalte unserer Träume beeinflussen."
|
||||
/>
|
||||
|
||||
{/* Socioeconomic Factors */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Sozioökonomische Faktoren"/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Urban vs Rural */}
|
||||
<DreamyCard color="blue">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaCity/>} color="blue"/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-3 text-center dreamy-text">Urbane vs. Rurale Träume</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-sm font-bold">Stadtbewohner:</span>
|
||||
<span className="text-sm">+43%</span>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div className="absolute top-0 left-0 h-full bg-blue-500 dark:bg-blue-600 rounded-full"
|
||||
style={{width: '43%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-2">Träume von Verkehr und Menschenmengen</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Stadtbewohner träumen 43% häufiger von Verkehr, Menschenmengen und urbanen Umgebungen als
|
||||
Menschen in ländlichen Gebieten. Ihre Träume enthalten auch mehr technologische Elemente und
|
||||
soziale Interaktionen mit Fremden.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* Income Level */}
|
||||
<DreamyCard color="emerald">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaMoneyBillWave/>} color="emerald"/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-3 text-center dreamy-text">Einkommensniveau</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-sm font-bold">Höhere Einkommen:</span>
|
||||
<span className="text-sm">-31%</span>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-emerald-500 dark:bg-emerald-600 rounded-full"
|
||||
style={{width: '31%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-2">Weniger Angstträume</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Menschen mit höherem Einkommen berichten von 31% weniger Angstträumen im Vergleich zu
|
||||
Personen mit niedrigerem Einkommen. Finanzielle Sicherheit korreliert mit positiveren
|
||||
Traumthemen und besserer Schlafqualität.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* Education Level */}
|
||||
<DreamyCard color="amber">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaGraduationCap/>} color="amber"/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-3 text-center dreamy-text">Bildungsgrad</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2 text-center">Komplexität der Traumnarration</h4>
|
||||
<div className="flex items-center justify-center space-x-2">
|
||||
<div className="text-center">
|
||||
<div className="h-16 w-4 bg-gray-200 dark:bg-gray-700 rounded-t-full relative">
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 bg-amber-500 dark:bg-amber-600 rounded-t-full"
|
||||
style={{height: '40%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1">Grundschule</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="h-16 w-4 bg-gray-200 dark:bg-gray-700 rounded-t-full relative">
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 bg-amber-500 dark:bg-amber-600 rounded-t-full"
|
||||
style={{height: '60%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1">Sekundar</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="h-16 w-4 bg-gray-200 dark:bg-gray-700 rounded-t-full relative">
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 bg-amber-500 dark:bg-amber-600 rounded-t-full"
|
||||
style={{height: '85%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1">Universität</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Universitätsabsolventen zeigen komplexere Traumnarrationen mit mehr Details, Charakteren und
|
||||
Handlungssträngen. Bildung korreliert mit der Fähigkeit, Träume detaillierter zu erinnern
|
||||
und zu beschreiben.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Environmental Factors */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Umweltfaktoren"/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Air Quality */}
|
||||
<DreamyCard color="rose">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaSmog/>} color="rose"/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-3 text-center dreamy-text">Luftqualität</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-sm font-bold">Schlechte Luftqualität:</span>
|
||||
<span className="text-sm">+28%</span>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div className="absolute top-0 left-0 h-full bg-rose-500 dark:bg-rose-600 rounded-full"
|
||||
style={{width: '28%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-2">Mehr Albträume</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Schlechte Luftqualität führt zu 28% mehr Albträumen und beeinträchtigt die Schlafqualität.
|
||||
Studien zeigen, dass Luftverschmutzung die REM-Schlafphasen verkürzt und zu fragmentierteren
|
||||
Träumen führt.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* Noise Level */}
|
||||
<DreamyCard color="purple">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaVolumeUp/>} color="purple"/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-3 text-center dreamy-text">Lärmpegel</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2 text-center">REM-Phasen Dauer</h4>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="text-right w-1/2">
|
||||
<p className="text-xs mb-1">Ruhige Umgebung</p>
|
||||
<div className="h-4 bg-gray-200 dark:bg-gray-700 rounded-full relative">
|
||||
<div
|
||||
className="absolute top-0 right-0 h-full bg-purple-500 dark:bg-purple-600 rounded-full"
|
||||
style={{width: '90%'}}></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
<p className="text-xs mb-1">Laute Umgebung</p>
|
||||
<div className="h-4 bg-gray-200 dark:bg-gray-700 rounded-full relative">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-purple-500 dark:bg-purple-600 rounded-full"
|
||||
style={{width: '60%'}}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Städtische Lärmbelastung fragmentiert Träume durch kürzere REM-Phasen. Selbst wenn der Lärm
|
||||
nicht zum Aufwachen führt, beeinflusst er die Traumkontinuität und -qualität negativ.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* Light Pollution */}
|
||||
<DreamyCard color="violet">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaLightbulb/>} color="violet"/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-3 text-center dreamy-text">Lichtverschmutzung</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2 text-center">Melatonin-Produktion</h4>
|
||||
<div className="relative pt-1">
|
||||
<div className="flex mb-2 items-center justify-between">
|
||||
<div>
|
||||
<span
|
||||
className="text-xs font-semibold inline-block py-1 px-2 uppercase rounded-full bg-violet-200 text-violet-800">
|
||||
Niedrig
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<span
|
||||
className="text-xs font-semibold inline-block py-1 px-2 uppercase rounded-full bg-violet-200 text-violet-800">
|
||||
Hoch
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="overflow-hidden h-2 mb-4 text-xs flex rounded bg-gray-200 dark:bg-gray-700">
|
||||
<div style={{width: "30%"}}
|
||||
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-violet-500 dark:bg-violet-600">
|
||||
<span className="text-[0.5rem] text-white">Hohe Lichtverschmutzung</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="overflow-hidden h-2 mb-4 text-xs flex rounded bg-gray-200 dark:bg-gray-700">
|
||||
<div style={{width: "75%"}}
|
||||
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-violet-500 dark:bg-violet-600">
|
||||
<span className="text-[0.5rem] text-white">Geringe Lichtverschmutzung</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Reduzierte Melatonin-Produktion durch Lichtverschmutzung beeinflusst die Traumintensität.
|
||||
Menschen in Gebieten mit geringer Lichtverschmutzung berichten von lebhafteren und
|
||||
intensiveren Träumen.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Combined Impact */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Kombinierte Auswirkungen"/>
|
||||
|
||||
<DreamyCard color="pink-red">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4 dreamy-text">Optimale vs. Suboptimale Bedingungen</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Optimale Bedingungen</h4>
|
||||
<ul className="list-disc list-inside text-sm space-y-1">
|
||||
<li>Ruhige, natürliche Umgebung</li>
|
||||
<li>Gute Luftqualität</li>
|
||||
<li>Minimale Lichtverschmutzung</li>
|
||||
<li>Finanzielle Sicherheit</li>
|
||||
<li>Ausgewogene Work-Life-Balance</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">Suboptimale Bedingungen</h4>
|
||||
<ul className="list-disc list-inside text-sm space-y-1">
|
||||
<li>Laute, urbane Umgebung</li>
|
||||
<li>Schlechte Luftqualität</li>
|
||||
<li>Hohe Lichtverschmutzung</li>
|
||||
<li>Finanzielle Unsicherheit</li>
|
||||
<li>Chronischer Stress</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4 dreamy-text">Auswirkungen auf Traumqualität</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Optimale Bedingungen führen zu:</h4>
|
||||
<ul className="list-disc list-inside text-sm space-y-1">
|
||||
<li>Längeren REM-Phasen</li>
|
||||
<li>Lebhafteren Träumen</li>
|
||||
<li>Besserer Traumerinnerung</li>
|
||||
<li>Positiveren Traumthemen</li>
|
||||
<li>Höherer Wahrscheinlichkeit für luzide Träume</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">Suboptimale Bedingungen führen zu:</h4>
|
||||
<ul className="list-disc list-inside text-sm space-y-1">
|
||||
<li>Fragmentierten REM-Phasen</li>
|
||||
<li>Häufigeren Albträumen</li>
|
||||
<li>Schlechterer Traumerinnerung</li>
|
||||
<li>Stressbeladenen Traumthemen</li>
|
||||
<li>Unterbrochenem Schlaf</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm mt-6">
|
||||
Die Kombination verschiedener Umwelt- und sozioökonomischer Faktoren hat einen kumulativen
|
||||
Effekt auf die Traumqualität. Die Verbesserung einzelner Faktoren kann bereits zu einer
|
||||
signifikanten Verbesserung der Traumqualität führen.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
|
||||
{/* Practical Tips */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Praktische Tipps für bessere Träume"/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<DreamyCard color="blue">
|
||||
<h3 className="text-lg font-bold mb-3 dreamy-text">Umweltfaktoren optimieren</h3>
|
||||
<ul className="list-disc list-inside text-sm space-y-2">
|
||||
<li>Verwende Verdunkelungsvorhänge, um Lichtverschmutzung zu reduzieren</li>
|
||||
<li>Nutze Luftreiniger für bessere Luftqualität im Schlafzimmer</li>
|
||||
<li>Setze Ohrstöpsel oder weißes Rauschen gegen Lärmbelästigung ein</li>
|
||||
<li>Halte die Schlafzimmertemperatur zwischen 16-18°C</li>
|
||||
<li>Vermeide blaues Licht von Bildschirmen mindestens eine Stunde vor dem Schlafengehen</li>
|
||||
</ul>
|
||||
</DreamyCard>
|
||||
|
||||
<DreamyCard color="emerald">
|
||||
<h3 className="text-lg font-bold mb-3 dreamy-text">Lebensstil-Anpassungen</h3>
|
||||
<ul className="list-disc list-inside text-sm space-y-2">
|
||||
<li>Etabliere eine regelmäßige Schlafenszeit und Aufwachzeit</li>
|
||||
<li>Praktiziere Entspannungstechniken vor dem Schlafengehen</li>
|
||||
<li>Führe ein Traumtagebuch, um die Traumerinnerung zu verbessern</li>
|
||||
<li>Reduziere Stress durch regelmäßige Bewegung und Meditation</li>
|
||||
<li>Vermeide schwere Mahlzeiten, Alkohol und Koffein vor dem Schlafengehen</li>
|
||||
</ul>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
138
src/pages/dreamarchive/ResearchLive.tsx
Normal file
138
src/pages/dreamarchive/ResearchLive.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import {FaCalendarAlt, FaClipboardCheck, FaGlobeEurope, FaUsers} from 'react-icons/fa';
|
||||
import mockResearchLive from '../../data/MockResearchLive';
|
||||
import HeroSection from '../../components/dreamarchive/HeroSection';
|
||||
import SectionHeader from '../../components/dreamarchive/SectionHeader';
|
||||
import DreamyCard from '../../components/dreamarchive/DreamyCard';
|
||||
import StudyCard from '../../components/dreamarchive/StudyCard';
|
||||
import IconWithBackground from '../../components/dreamarchive/IconWithBackground';
|
||||
|
||||
export default function ResearchLive() {
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<HeroSection
|
||||
containerTitle="Sei Teil der Traumforschung"
|
||||
description="Entdecke laufende Forschungsprojekte, nimm an Studien teil und lerne von führenden Traumforschern aus der ganzen Welt."
|
||||
/>
|
||||
|
||||
{/* Citizen Science */}
|
||||
<div className="mb-12">
|
||||
<DreamyCard color="violet">
|
||||
<div className="flex items-center mb-6">
|
||||
<IconWithBackground
|
||||
icon={<FaCalendarAlt/>}
|
||||
color="violet"
|
||||
size={28}
|
||||
className="mr-4"
|
||||
/>
|
||||
<h3 className="text-xl font-bold dreamy-text">Wie du zur Wissenschaft beitragen kannst</h3>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
||||
{mockResearchLive.citizenScienceProjects.map((project) => {
|
||||
// Dynamically determine which icon component to use
|
||||
let IconComponent;
|
||||
switch (project.icon) {
|
||||
case 'FaClipboardCheck':
|
||||
IconComponent = FaClipboardCheck;
|
||||
break;
|
||||
case 'FaGlobeEurope':
|
||||
IconComponent = FaGlobeEurope;
|
||||
break;
|
||||
case 'FaUsers':
|
||||
IconComponent = FaUsers;
|
||||
break;
|
||||
default:
|
||||
IconComponent = FaClipboardCheck;
|
||||
}
|
||||
|
||||
return (<div key={project.id}
|
||||
className="bg-white/20 dark:bg-black/20 p-4 rounded-lg flex flex-col min-h-[200px]">
|
||||
<div className="flex justify-center mb-3">
|
||||
<div className="p-2 bg-violet-500/20 rounded-full">
|
||||
<IconComponent className="text-violet-600 dark:text-violet-400" size={20}/>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-bold mb-2 text-center">{project.title}</h4>
|
||||
<p className="text-sm flex-grow">
|
||||
{project.description}
|
||||
</p>
|
||||
<div className="mt-3 text-center">
|
||||
{project.optedIn ? (
|
||||
<button
|
||||
className="py-1 px-3 text-white text-xs rounded-lg transition-colors">
|
||||
Danke!
|
||||
</button>) : (
|
||||
<button
|
||||
className="py-1 px-3 dreamy-button text-green text-xs rounded-lg transition-colors">
|
||||
Beitragen
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Citizen Science-Projekte ermöglichen es jedem, zur Traumforschung beizutragen. Deine Teilnahme
|
||||
hilft Wissenschaftlern, größere und vielfältigere Datensätze zu sammeln, was zu robusteren
|
||||
Forschungsergebnissen führt.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Current Studies */}
|
||||
<div className="mb-12">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{mockResearchLive.currentStudies.slice(0, 2).map((study) => (
|
||||
<StudyCard key={study.id} study={study}/>))}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-6">
|
||||
{mockResearchLive.currentStudies.slice(2, 4).map((study) => (
|
||||
<StudyCard key={study.id} study={study}/>))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Upcoming Events */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Kommende Veranstaltungen"/>
|
||||
|
||||
<DreamyCard color="purple">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-left p-2">Datum</th>
|
||||
<th className="text-left p-2">Veranstaltung</th>
|
||||
<th className="text-left p-2">Ort</th>
|
||||
<th className="text-left p-2">Typ</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{mockResearchLive.upcomingEvents.map((event, index) => (
|
||||
<tr key={event.id} className={index % 2 === 0 ? "bg-white/10 dark:bg-black/10" : ""}>
|
||||
<td className="p-2">{event.date}</td>
|
||||
<td className="p-2">{event.title}</td>
|
||||
<td className="p-2">{event.location}</td>
|
||||
<td className="p-2">
|
||||
<span
|
||||
className={`bg-${event.typeColor}-100 dark:bg-${event.typeColor}-900 text-${event.typeColor}-800 dark:text-${event.typeColor}-200 text-xs px-2 py-0.5 rounded-full`}>
|
||||
{event.type}
|
||||
</span>
|
||||
</td>
|
||||
</tr>))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 text-center">
|
||||
<button
|
||||
className="py-2 px-4 bg-purple-500 hover:bg-purple-600 text-white rounded-lg transition-colors">
|
||||
Alle Veranstaltungen anzeigen
|
||||
</button>
|
||||
</div>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
558
src/pages/dreamarchive/Technology.tsx
Normal file
558
src/pages/dreamarchive/Technology.tsx
Normal file
@@ -0,0 +1,558 @@
|
||||
import {getTextStyle} from '../../styles/StyleUtils';
|
||||
import {FaBrain, FaChartBar, FaChartPie, FaLaptopCode, FaMicrochip, FaRobot, FaVrCardboard} from 'react-icons/fa';
|
||||
import HeroSection from '../../components/dreamarchive/HeroSection';
|
||||
import SectionHeader from '../../components/dreamarchive/SectionHeader';
|
||||
import DreamyCard from '../../components/dreamarchive/DreamyCard';
|
||||
import IconWithBackground from '../../components/dreamarchive/IconWithBackground';
|
||||
import {useEffect, useRef} from 'react';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
// Dream types data with percentages and colors
|
||||
const dreamTypesData = [
|
||||
{type: "Angstträume", percentage: 34, color: "#ef4444", darkColor: "#dc2626", note: "Global durchschnittlich"},
|
||||
{type: "Soziale Träume", percentage: 28, color: "#3b82f6", darkColor: "#2563eb", note: "Kulturelle Variationen"},
|
||||
{type: "Flugträume", percentage: 18, color: "#a855f7", darkColor: "#9333ea", note: "Persönlichkeitsabhängig"},
|
||||
{type: "Sexuelle Träume", percentage: 12, color: "#ec4899", darkColor: "#db2777", note: "Altersabhängig"},
|
||||
{type: "Verfolgungsträume", percentage: 8, color: "#f97316", darkColor: "#ea580c", note: "Stresskorreliert"}
|
||||
];
|
||||
|
||||
// D3.js Pie Chart Component
|
||||
function D3PieChart() {
|
||||
const svgRef = useRef<SVGSVGElement>(null);
|
||||
const tooltipRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
useEffect(() => {
|
||||
if (!svgRef.current || !tooltipRef.current || !containerRef.current) return;
|
||||
|
||||
// Clear any existing SVG content
|
||||
d3.select(svgRef.current).selectAll("*").remove();
|
||||
|
||||
// Set up dimensions
|
||||
const width = svgRef.current.clientWidth;
|
||||
const height = svgRef.current.clientHeight;
|
||||
const margin = 10;
|
||||
const radius = Math.min(width, height) / 2 - margin;
|
||||
|
||||
// Create SVG
|
||||
const svg = d3.select(svgRef.current)
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${width / 2}, ${height / 2})`);
|
||||
|
||||
// Create pie generator
|
||||
const pie = d3.pie<typeof dreamTypesData[0]>()
|
||||
.value(d => d.percentage)
|
||||
.sort(null);
|
||||
|
||||
// Create arc generator
|
||||
const arc = d3.arc<d3.PieArcDatum<typeof dreamTypesData[0]>>()
|
||||
.innerRadius(0)
|
||||
.outerRadius(radius);
|
||||
|
||||
// Get tooltip element
|
||||
const tooltip = d3.select(tooltipRef.current);
|
||||
|
||||
// Function to show tooltip
|
||||
const showTooltip = (event: MouseEvent | TouchEvent, d: d3.PieArcDatum<typeof dreamTypesData[0]>) => {
|
||||
const data = d.data;
|
||||
|
||||
// Set tooltip content
|
||||
tooltip.html(`
|
||||
<div class="font-bold">${data.type}</div>
|
||||
<div>${data.percentage}%</div>
|
||||
<div class="text-xs opacity-75">${data.note}</div>
|
||||
`);
|
||||
|
||||
// Make tooltip visible
|
||||
tooltip
|
||||
.style("opacity", 1)
|
||||
.style("visibility", "visible");
|
||||
|
||||
// Position tooltip
|
||||
const containerRect = containerRef.current!.getBoundingClientRect();
|
||||
let x, y;
|
||||
|
||||
if (event instanceof MouseEvent) {
|
||||
x = event.clientX - containerRect.left;
|
||||
y = event.clientY - containerRect.top;
|
||||
} else {
|
||||
// TouchEvent
|
||||
const touch = (event as TouchEvent).touches[0];
|
||||
x = touch.clientX - containerRect.left;
|
||||
y = touch.clientY - containerRect.top;
|
||||
}
|
||||
|
||||
// Adjust position to avoid going off the container
|
||||
const tooltipRect = tooltipRef.current!.getBoundingClientRect();
|
||||
if (x + tooltipRect.width > containerRect.width) {
|
||||
x = x - tooltipRect.width;
|
||||
}
|
||||
if (y + tooltipRect.height > containerRect.height) {
|
||||
y = y - tooltipRect.height;
|
||||
}
|
||||
|
||||
tooltip
|
||||
.style("left", `${x + 10}px`)
|
||||
.style("top", `${y + 10}px`);
|
||||
};
|
||||
|
||||
// Function to hide tooltip
|
||||
const hideTooltip = () => {
|
||||
tooltip
|
||||
.style("opacity", 0)
|
||||
.style("visibility", "hidden");
|
||||
};
|
||||
|
||||
// Create pie chart with event handlers
|
||||
svg.selectAll("path")
|
||||
.data(pie(dreamTypesData))
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("d", arc)
|
||||
.attr("fill", d => isDarkMode ? d.data.darkColor : d.data.color)
|
||||
.attr("stroke", "white")
|
||||
.style("stroke-width", "1px")
|
||||
.style("cursor", "pointer")
|
||||
// Desktop hover events
|
||||
.on("mouseover", function (event, d) {
|
||||
// Calculate centroid for this arc to ensure zoom is centered properly
|
||||
const centroid = arc.centroid(d);
|
||||
const x = centroid[0];
|
||||
const y = centroid[1];
|
||||
|
||||
d3.select(this).transition().duration(200)
|
||||
.attr("opacity", 0.8)
|
||||
.attr("stroke-width", "2px")
|
||||
// Apply zoom transformation centered on the arc's centroid
|
||||
.attr("transform", `translate(${x},${y}) scale(1.05) translate(${-x},${-y})`);
|
||||
showTooltip(event, d);
|
||||
})
|
||||
.on("mouseout", function () {
|
||||
d3.select(this).transition().duration(200)
|
||||
.attr("opacity", 1)
|
||||
.attr("stroke-width", "1px")
|
||||
.attr("transform", null); // Completely remove the transform to reset zoom
|
||||
hideTooltip();
|
||||
})
|
||||
// Mobile/touch events
|
||||
.on("touchstart", function (event, d) {
|
||||
// Stop propagation to prevent document touchstart from firing
|
||||
event.stopPropagation();
|
||||
// Prevent default to avoid any browser handling
|
||||
event.preventDefault();
|
||||
|
||||
// Store a reference to the element without using 'this'
|
||||
const element = event.currentTarget;
|
||||
|
||||
// Calculate centroid for this arc to ensure zoom is centered properly
|
||||
const centroid = arc.centroid(d);
|
||||
const x = centroid[0];
|
||||
const y = centroid[1];
|
||||
|
||||
// Visual feedback
|
||||
d3.select(element).transition().duration(200)
|
||||
.attr("opacity", 0.8)
|
||||
.attr("stroke-width", "2px")
|
||||
// Apply zoom transformation centered on the arc's centroid
|
||||
.attr("transform", `translate(${x},${y}) scale(1.05) translate(${-x},${-y})`);
|
||||
|
||||
// Show tooltip
|
||||
showTooltip(event, d);
|
||||
|
||||
// Add a temporary touchend handler to reset the visual state
|
||||
// but keep the tooltip visible
|
||||
document.addEventListener("touchend", function () {
|
||||
d3.select(element).transition().duration(200)
|
||||
.attr("opacity", 1)
|
||||
.attr("stroke-width", "1px")
|
||||
.attr("transform", null); // Completely remove the transform to reset zoom
|
||||
}, {once: true});
|
||||
})
|
||||
.on("click", function (event, d) {
|
||||
event.stopPropagation();
|
||||
showTooltip(event, d);
|
||||
});
|
||||
|
||||
// Add center circle
|
||||
svg.append("circle")
|
||||
.attr("cx", 0)
|
||||
.attr("cy", 0)
|
||||
.attr("r", radius * 0.4)
|
||||
.attr("fill", isDarkMode ? "#1f2937" : "#ffffff")
|
||||
.attr("stroke", isDarkMode ? "#374151" : "#e5e7eb")
|
||||
.style("stroke-width", "1px");
|
||||
|
||||
// Add center text
|
||||
svg.append("text")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("dy", "0.35em")
|
||||
.attr("class", "text-sm font-bold")
|
||||
.attr("fill", isDarkMode ? "#e5e7eb" : "#1f2937")
|
||||
.text("100%");
|
||||
|
||||
// Create a function to handle document touchstart that doesn't immediately hide the tooltip
|
||||
const handleDocumentTouchStart = (event: TouchEvent) => {
|
||||
// Only hide the tooltip if the touch is outside the pie chart segments
|
||||
const paths = svg.selectAll("path").nodes();
|
||||
const touchTarget = document.elementFromPoint(
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY
|
||||
);
|
||||
|
||||
// Don't hide if touching a pie segment
|
||||
if (paths.some(path => path === touchTarget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hideTooltip();
|
||||
};
|
||||
|
||||
// Add click event to document to hide tooltip when clicking outside
|
||||
document.addEventListener("click", hideTooltip);
|
||||
document.addEventListener("touchstart", handleDocumentTouchStart);
|
||||
|
||||
// Cleanup event listeners on unmount
|
||||
return () => {
|
||||
document.removeEventListener("click", hideTooltip);
|
||||
document.removeEventListener("touchstart", handleDocumentTouchStart);
|
||||
};
|
||||
}, [isDarkMode]);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="relative w-full aspect-square max-w-xs mx-auto">
|
||||
<svg ref={svgRef} className="w-full h-full"></svg>
|
||||
<div
|
||||
ref={tooltipRef}
|
||||
className="absolute pointer-events-none bg-white dark:bg-gray-800 p-2 rounded shadow-lg text-sm z-10 transition-opacity duration-200"
|
||||
style={{
|
||||
opacity: 0,
|
||||
visibility: 'hidden',
|
||||
maxWidth: '150px',
|
||||
border: '1px solid',
|
||||
borderColor: isDarkMode ? 'rgba(75, 85, 99, 0.5)' : 'rgba(229, 231, 235, 0.5)'
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Technology() {
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<HeroSection
|
||||
containerTitle="Die Zukunft der Traumforschung"
|
||||
description="Entdecke bahnbrechende Technologien, die uns helfen, Träume besser zu verstehen, zu analysieren und sogar zu steuern."
|
||||
/>
|
||||
|
||||
{/* Latest Developments */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Neueste Entwicklungen"/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* EEG-based Dream Detection */}
|
||||
<DreamyCard color="blue" className="h-full flex flex-col">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaBrain/>} color="blue"/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">EEG-basierte Traumdetektion</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-sm font-bold">Genauigkeit:</span>
|
||||
<span className="text-sm">85%</span>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div className="absolute top-0 left-0 h-full bg-blue-500 dark:bg-blue-600 rounded-full"
|
||||
style={{width: '85%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-2 text-center">Automatische Traumerkennung</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Moderne EEG-Technologie kann mit 85% Genauigkeit erkennen, wann eine Person träumt und in
|
||||
welcher Traumphase sie sich befindet. Dies ermöglicht gezielte Traumforschung und
|
||||
-intervention.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* DreamNet Framework */}
|
||||
<DreamyCard color="purple" className="h-full flex flex-col">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaLaptopCode/>} color="purple"/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">DreamNet-Framework</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-sm font-bold">Genauigkeit:</span>
|
||||
<span className="text-sm">99%</span>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-purple-500 dark:bg-purple-600 rounded-full"
|
||||
style={{width: '99%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-2 text-center">Multimodale Traumanalyse</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Das DreamNet-Framework kombiniert EEG-Daten, Augenbewegungen, Herzfrequenz und
|
||||
Körpertemperatur für eine präzise Traumanalyse. KI-Algorithmen interpretieren diese Daten
|
||||
und erstellen detaillierte Traumprofile.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* Lucid Dreaming Control */}
|
||||
<DreamyCard color="emerald" className="h-full flex flex-col">
|
||||
<div className="flex justify-center mb-4">
|
||||
<IconWithBackground icon={<FaVrCardboard/>} color="emerald"/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-center dreamy-text">Lucid Dreaming Control</h3>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2 text-center">Virtuelle Autosteuerung</h4>
|
||||
<p className="text-xs text-center mb-2">durch Traum-Muskelbewegungen</p>
|
||||
<div className="flex justify-center">
|
||||
<div
|
||||
className="relative w-24 h-24 rounded-full bg-emerald-100 dark:bg-emerald-900 flex items-center justify-center">
|
||||
<div
|
||||
className="absolute w-16 h-16 rounded-full bg-emerald-200 dark:bg-emerald-800 flex items-center justify-center">
|
||||
<div
|
||||
className="absolute w-8 h-8 rounded-full bg-emerald-500 dark:bg-emerald-600 flex items-center justify-center text-white">
|
||||
<FaRobot size={16}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Bahnbrechende Forschung ermöglicht es Personen in luziden Träumen, durch subtile
|
||||
Augenbewegungen und Muskelsignale mit der Außenwelt zu kommunizieren und sogar virtuelle
|
||||
Objekte zu steuern.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dream Type Classification */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Traumtypen-Klassifikation"/>
|
||||
|
||||
<DreamyCard color="rose">
|
||||
<div className="flex items-center justify-center mb-6">
|
||||
<IconWithBackground icon={<FaChartPie/>} color="rose" className="mr-3"/>
|
||||
<h3 className="text-xl font-bold dreamy-text">Globale Verteilung der Traumtypen</h3>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
<div>
|
||||
{/* D3.js Pie Chart */}
|
||||
<D3PieChart/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center">
|
||||
<div className="w-4 h-4 bg-red-500 dark:bg-red-600 mr-2"></div>
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-bold">Angstträume</span>
|
||||
<span className="text-sm">34%</span>
|
||||
</div>
|
||||
<div
|
||||
className="relative h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-red-500 dark:bg-red-600 rounded-full"
|
||||
style={{width: '34%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1" style={getTextStyle('muted')}>Global
|
||||
durchschnittlich</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<div className="w-4 h-4 bg-blue-500 dark:bg-blue-600 mr-2"></div>
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-bold">Soziale Träume</span>
|
||||
<span className="text-sm">28%</span>
|
||||
</div>
|
||||
<div
|
||||
className="relative h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-blue-500 dark:bg-blue-600 rounded-full"
|
||||
style={{width: '28%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1" style={getTextStyle('muted')}>Kulturelle
|
||||
Variationen</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<div className="w-4 h-4 bg-purple-500 dark:bg-purple-600 mr-2"></div>
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-bold">Flugträume</span>
|
||||
<span className="text-sm">18%</span>
|
||||
</div>
|
||||
<div
|
||||
className="relative h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-purple-500 dark:bg-purple-600 rounded-full"
|
||||
style={{width: '18%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1"
|
||||
style={getTextStyle('muted')}>Persönlichkeitsabhängig</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<div className="w-4 h-4 bg-pink-500 dark:bg-pink-600 mr-2"></div>
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-bold">Sexuelle Träume</span>
|
||||
<span className="text-sm">12%</span>
|
||||
</div>
|
||||
<div
|
||||
className="relative h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-pink-500 dark:bg-pink-600 rounded-full"
|
||||
style={{width: '12%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1" style={getTextStyle('muted')}>Altersabhängig</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<div className="w-4 h-4 bg-orange-500 dark:bg-orange-600 mr-2"></div>
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-bold">Verfolgungsträume</span>
|
||||
<span className="text-sm">8%</span>
|
||||
</div>
|
||||
<div
|
||||
className="relative h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-orange-500 dark:bg-orange-600 rounded-full"
|
||||
style={{width: '8%'}}></div>
|
||||
</div>
|
||||
<p className="text-xs mt-1" style={getTextStyle('muted')}>Stresskorreliert</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm" style={getTextStyle('normal')}>
|
||||
Moderne KI-Algorithmen können Träume basierend auf ihrem Inhalt, emotionalen Ton und narrativen
|
||||
Strukturen klassifizieren. Diese Klassifikation hilft Forschern, Muster in großen
|
||||
Traumdatensätzen zu erkennen und kulturübergreifende Vergleiche anzustellen.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
|
||||
{/* Future Technologies */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Zukunftstechnologien"/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* Dream Recording */}
|
||||
<DreamyCard color="violet" className="h-full flex flex-col">
|
||||
<div className="flex items-center mb-4">
|
||||
<IconWithBackground icon={<FaMicrochip/>} color="violet" className="mr-4"/>
|
||||
<h3 className="text-xl font-bold dreamy-text">Traumaufzeichnung</h3>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Visuelle Rekonstruktion von Träumen</h4>
|
||||
<p className="text-sm">
|
||||
Forscher arbeiten an Technologien, die visuelle Inhalte aus Träumen rekonstruieren
|
||||
können, indem sie Hirnaktivitätsmuster in visuelle Darstellungen umwandeln.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Die nächste Generation von Traumtechnologie zielt darauf ab, Träume als Video aufzuzeichnen
|
||||
und abzuspielen. Erste Prototypen können bereits einfache visuelle Elemente aus der
|
||||
Hirnaktivität während des Träumens rekonstruieren.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
|
||||
{/* Dream Sharing */}
|
||||
<DreamyCard color="amber" className="h-full flex flex-col">
|
||||
<div className="flex items-center mb-4">
|
||||
<IconWithBackground icon={<FaChartBar/>} color="amber" className="mr-4"/>
|
||||
<h3 className="text-xl font-bold dreamy-text">Traumaustausch</h3>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Gemeinsame Traumwelten</h4>
|
||||
<p className="text-sm">
|
||||
Experimentelle Technologien ermöglichen es zwei oder mehr Personen, ähnliche
|
||||
Traumszenarien zu erleben und in begrenztem Umfang miteinander zu interagieren.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm flex-grow" style={getTextStyle('normal')}>
|
||||
Forscher entwickeln Methoden, um Träume zwischen Individuen zu teilen oder sogar gemeinsame
|
||||
Traumwelten zu schaffen. Diese Technologie könnte revolutionäre Anwendungen in Therapie,
|
||||
Kreativität und zwischenmenschlicher Kommunikation haben.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Ethical Considerations */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Ethische Überlegungen"/>
|
||||
|
||||
<DreamyCard color="blue">
|
||||
<h3 className="text-xl font-bold mb-4 dreamy-text">Wichtige ethische Fragen</h3>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">Privatsphäre</h4>
|
||||
<p className="text-sm">
|
||||
Wem gehören Traumdaten? Wie können wir sicherstellen, dass die intimsten Gedanken einer
|
||||
Person geschützt bleiben?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">Manipulation</h4>
|
||||
<p className="text-sm">
|
||||
Könnte Traumtechnologie für Werbung, Propaganda oder andere Formen der Beeinflussung
|
||||
missbraucht werden?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">Identität</h4>
|
||||
<p className="text-sm">
|
||||
Wie beeinflussen Traummanipulationen unser Selbstverständnis und unsere persönliche
|
||||
Entwicklung?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">Zugang</h4>
|
||||
<p className="text-sm">
|
||||
Wer hat Zugang zu fortschrittlicher Traumtechnologie? Könnte dies zu neuen sozialen
|
||||
Ungleichheiten führen?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm" style={getTextStyle('normal')}>
|
||||
Mit der rasanten Entwicklung der Traumtechnologie müssen wir auch die ethischen Implikationen
|
||||
sorgfältig betrachten. Forscher und Ethiker arbeiten gemeinsam an Richtlinien für
|
||||
verantwortungsvolle Traumforschung und -technologie.
|
||||
</p>
|
||||
</DreamyCard>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
353
src/pages/dreamarchive/UserDreams.tsx
Normal file
353
src/pages/dreamarchive/UserDreams.tsx
Normal file
@@ -0,0 +1,353 @@
|
||||
import {getBackgroundStyle, getTextStyle} from '../../styles/StyleUtils';
|
||||
import {FaChartLine, FaRegCommentDots, FaRegLightbulb, FaUser} from 'react-icons/fa';
|
||||
import {MockUserMap} from '../../data/MockUsers';
|
||||
import mockUserDreams from '../../data/MockUserDreams';
|
||||
|
||||
export default function UserDreams() {
|
||||
const currentUser = MockUserMap.get(4); // Neo Quantum
|
||||
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-12 sm:mb-16 relative z-10">
|
||||
<div className="animate-pulse flex flex-col items-center mb-8 sm:mb-12">
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4 dream-title">Deine Träume im
|
||||
Kontext</h1>
|
||||
<p className="text-lg sm:text-xl dreamy-text">Einordnung deiner Träume in die globale
|
||||
Traumdatenbank</p>
|
||||
</div>
|
||||
<div
|
||||
className="dream-container floating max-w-3xl mx-auto backdrop-blur-sm bg-white/10 dark:bg-white/5 rounded-3xl p-4 sm:p-6 md:p-8"
|
||||
style={{animationDelay: '0.2s'}}>
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center mb-3 sm:mb-4">
|
||||
<h2 className="dream-title text-xl sm:text-2xl">Hallo, {currentUser?.name || 'Neo'}</h2>
|
||||
</div>
|
||||
<p className="mb-4 sm:mb-6 md:mb-8 text-sm sm:text-base md:text-lg" style={{color: 'var(--text)'}}>
|
||||
Entdecke, wie sich deine Träume im Vergleich zur globalen Traumdatenbank verhalten und wie sie
|
||||
sich im Laufe der Zeit verändert haben.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* User Profile Overview */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Dein Traumprofil</h2>
|
||||
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle('purple')}>
|
||||
<div className="flex flex-col md:flex-row items-center mb-6">
|
||||
<div className="mb-4 md:mb-0 md:mr-6">
|
||||
{currentUser?.profilePicture ? (<img
|
||||
src={`/assets/profiles/${currentUser.profilePicture}`}
|
||||
alt={currentUser.name}
|
||||
className="w-24 h-24 rounded-full object-cover border-4 border-purple-300 dark:border-purple-700"
|
||||
/>) : (<div
|
||||
className="w-24 h-24 rounded-full bg-purple-200 dark:bg-purple-800 flex items-center justify-center">
|
||||
<FaUser className="text-purple-600 dark:text-purple-400" size={32}/>
|
||||
</div>)}
|
||||
</div>
|
||||
|
||||
<div className="text-center md:text-left">
|
||||
<h3 className="text-xl font-bold mb-2 dreamy-text">{currentUser?.name || 'Neo Quantum'}</h3>
|
||||
<p className="text-sm mb-1" style={getTextStyle()}>Traumaufzeichnungen: <span
|
||||
className="font-bold">42</span></p>
|
||||
<p className="text-sm mb-1" style={getTextStyle()}>Aktive Tage: <span
|
||||
className="font-bold">{currentUser?.streakDays || 14}</span></p>
|
||||
<p className="text-sm" style={getTextStyle()}>Mitglied seit: <span
|
||||
className="font-bold">März 2023</span></p>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 mt-4 md:mt-0 md:ml-6">
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2 text-center">Deine häufigsten Traumthemen</h4>
|
||||
<div className="space-y-2">
|
||||
{mockUserDreams.userDreamThemes.map((item, index) => (
|
||||
<div key={index}>
|
||||
<div className="flex justify-between text-xs mb-1">
|
||||
<span>{item.theme}</span>
|
||||
<span>{item.percentage}%</span>
|
||||
</div>
|
||||
<div
|
||||
className="relative h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className={`absolute top-0 left-0 h-full bg-${item.color}-500 dark:bg-${item.color}-600 rounded-full`}
|
||||
style={{width: `${item.percentage}%`}}></div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Global Comparison */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Vergleich mit globaler Traumdatenbank</h2>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* Dream Emotions */}
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle('blue')}>
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-3 bg-blue-500/20 rounded-full mr-4">
|
||||
<FaRegCommentDots className="text-blue-600 dark:text-blue-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold dreamy-text">Traumemotionen</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<span className="text-sm font-bold">Positive Emotionen</span>
|
||||
<div className="flex items-center">
|
||||
<span
|
||||
className="text-xs mr-2">Global: {mockUserDreams.dreamEmotionsComparison.positive.global}%</span>
|
||||
<span
|
||||
className="text-xs font-bold">Du: {mockUserDreams.dreamEmotionsComparison.positive.user}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-gray-400 dark:bg-gray-600 rounded-full"
|
||||
style={{width: `${mockUserDreams.dreamEmotionsComparison.positive.global}%`}}></div>
|
||||
<div
|
||||
className={`absolute top-0 left-0 h-full bg-${mockUserDreams.dreamEmotionsComparison.positive.color}-500 dark:bg-${mockUserDreams.dreamEmotionsComparison.positive.color}-600 rounded-full border-r-2 border-white dark:border-gray-900`}
|
||||
style={{width: `${mockUserDreams.dreamEmotionsComparison.positive.user}%`}}></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<span className="text-sm font-bold">Negative Emotionen</span>
|
||||
<div className="flex items-center">
|
||||
<span
|
||||
className="text-xs mr-2">Global: {mockUserDreams.dreamEmotionsComparison.negative.global}%</span>
|
||||
<span
|
||||
className="text-xs font-bold">Du: {mockUserDreams.dreamEmotionsComparison.negative.user}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-gray-400 dark:bg-gray-600 rounded-full"
|
||||
style={{width: `${mockUserDreams.dreamEmotionsComparison.negative.global}%`}}></div>
|
||||
<div
|
||||
className={`absolute top-0 left-0 h-full bg-${mockUserDreams.dreamEmotionsComparison.negative.color}-500 dark:bg-${mockUserDreams.dreamEmotionsComparison.negative.color}-600 rounded-full border-r-2 border-white dark:border-gray-900`}
|
||||
style={{width: `${mockUserDreams.dreamEmotionsComparison.negative.user}%`}}></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<span className="text-sm font-bold">Neutrale Emotionen</span>
|
||||
<div className="flex items-center">
|
||||
<span
|
||||
className="text-xs mr-2">Global: {mockUserDreams.dreamEmotionsComparison.neutral.global}%</span>
|
||||
<span
|
||||
className="text-xs font-bold">Du: {mockUserDreams.dreamEmotionsComparison.neutral.user}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full bg-gray-400 dark:bg-gray-600 rounded-full"
|
||||
style={{width: `${mockUserDreams.dreamEmotionsComparison.neutral.global}%`}}></div>
|
||||
<div
|
||||
className={`absolute top-0 left-0 h-full bg-${mockUserDreams.dreamEmotionsComparison.neutral.color}-500 dark:bg-${mockUserDreams.dreamEmotionsComparison.neutral.color}-600 rounded-full border-r-2 border-white dark:border-gray-900`}
|
||||
style={{width: `${mockUserDreams.dreamEmotionsComparison.neutral.user}%`}}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm mt-4">
|
||||
Im Vergleich zum globalen Durchschnitt hast du deutlich mehr positive und weniger negative
|
||||
Emotionen in deinen Träumen. Dies könnte auf ein höheres Wohlbefinden oder eine
|
||||
optimistischere Grundeinstellung hindeuten.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Dream Themes */}
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle('emerald')}>
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-3 bg-emerald-500/20 rounded-full mr-4">
|
||||
<FaRegLightbulb className="text-emerald-600 dark:text-emerald-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold dreamy-text">Traumthemen</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="bg-white/20 dark:bg-black/20 p-3 rounded-lg text-center">
|
||||
<h4 className="font-bold mb-1 text-sm">Deine Top-Themen</h4>
|
||||
<ol className="text-xs text-left list-decimal list-inside">
|
||||
{mockUserDreams.dreamThemesComparison.userTopThemes.map((item, index) => (
|
||||
<li key={index}>{item.theme} ({item.percentage}%)</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-3 rounded-lg text-center">
|
||||
<h4 className="font-bold mb-1 text-sm">Globale Top-Themen</h4>
|
||||
<ol className="text-xs text-left list-decimal list-inside">
|
||||
{mockUserDreams.dreamThemesComparison.globalTopThemes.map((item, index) => (
|
||||
<li key={index}>{item.theme} ({item.percentage}%)</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-3 rounded-lg">
|
||||
<h4 className="font-bold mb-2 text-sm text-center">Einzigartige Aspekte deiner
|
||||
Träume</h4>
|
||||
<ul className="text-xs list-disc list-inside space-y-1">
|
||||
{mockUserDreams.uniqueDreamAspects.map((aspect, index) => (
|
||||
<li key={index}>{aspect}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm mt-4">
|
||||
Deine Traumthemen unterscheiden sich deutlich vom globalen Durchschnitt. Während viele
|
||||
Menschen von Ängsten und Sorgen träumen, fokussieren sich deine Träume mehr auf positive
|
||||
Erfahrungen und kreative Exploration.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dream Changes Over Time */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Persönliche Traumveränderung über Zeit</h2>
|
||||
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle('rose')}>
|
||||
<div className="flex items-center mb-6">
|
||||
<div className="p-3 bg-rose-500/20 rounded-full mr-4">
|
||||
<FaChartLine className="text-rose-600 dark:text-rose-400" size={28}/>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold dreamy-text">Entwicklung deiner Traumthemen</h3>
|
||||
</div>
|
||||
|
||||
{/* Timeline Chart (Mock) */}
|
||||
<div className="mb-6 overflow-x-auto">
|
||||
<div className="min-w-[600px]">
|
||||
<div className="relative h-60">
|
||||
{/* X-Axis (Time) */}
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 h-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="absolute bottom-0 left-0 right-0 flex justify-between text-xs"
|
||||
style={getTextStyle('muted')}>
|
||||
{mockUserDreams.dreamThemeTimeline.timePoints.map((timePoint, index) => (
|
||||
<div className="text-center" key={index}>
|
||||
<div className="absolute bottom-0 h-2 w-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="mt-2">{timePoint}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Y-Axis (Percentage) */}
|
||||
<div className="absolute top-0 bottom-0 left-0 w-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="absolute top-0 bottom-0 left-0 flex flex-col justify-between text-xs"
|
||||
style={getTextStyle('muted')}>
|
||||
<div>
|
||||
<div
|
||||
className="absolute left-0 top-0 w-2 h-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="transform -translate-y-1/2 -translate-x-full mr-1">100%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="absolute left-0 top-1/4 w-2 h-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="transform -translate-y-1/2 -translate-x-full mr-1">75%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="absolute left-0 top-2/4 w-2 h-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="transform -translate-y-1/2 -translate-x-full mr-1">50%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="absolute left-0 top-3/4 w-2 h-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="transform -translate-y-1/2 -translate-x-full mr-1">25%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="absolute left-0 bottom-0 w-2 h-px bg-gray-300 dark:bg-gray-600"></div>
|
||||
<div className="transform -translate-y-1/2 -translate-x-full mr-1">0%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Data Lines */}
|
||||
{mockUserDreams.dreamThemeTimeline.themes.map((theme, index) => {
|
||||
// Convert dataPoints to SVG points format
|
||||
// Each point is a percentage of the way across (x) and a percentage of the way down (y)
|
||||
const points = theme.dataPoints.map((point, i) => {
|
||||
const x = (i / (theme.dataPoints.length - 1)) * 100;
|
||||
return `${x},${point}`;
|
||||
}).join(' ');
|
||||
|
||||
return (
|
||||
<svg key={index} className="absolute inset-0" viewBox="0 0 100 100"
|
||||
preserveAspectRatio="none">
|
||||
<polyline
|
||||
points={points}
|
||||
fill="none"
|
||||
stroke={theme.color}
|
||||
strokeWidth="2"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Legend */}
|
||||
<div className="absolute top-0 right-0 bg-white/50 dark:bg-black/50 p-2 rounded-lg">
|
||||
{mockUserDreams.dreamThemeTimeline.themes.map((theme, index) => (
|
||||
<div key={index} className="flex items-center mb-1">
|
||||
<div className="w-3 h-3 mr-2" style={{backgroundColor: theme.color}}></div>
|
||||
<span className="text-xs">{theme.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/20 dark:bg-black/20 p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold mb-2">Schlüsselerkenntnisse</h4>
|
||||
<ul className="list-disc list-inside text-sm space-y-1">
|
||||
{mockUserDreams.dreamInsights.map((insight, index) => (
|
||||
<li key={index}>{insight}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
Die Analyse deiner Traumdaten über Zeit zeigt eine deutliche Entwicklung hin zu positiveren und
|
||||
kreativeren Traumthemen. Diese Veränderung könnte mit persönlichem Wachstum, veränderten
|
||||
Lebensumständen oder bewusster Traumarbeit zusammenhängen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Personalized Recommendations */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-2xl font-bold mb-6 dream-title">Personalisierte Empfehlungen</h2>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle('violet')}>
|
||||
<h3 className="text-lg font-bold mb-3 dreamy-text">Für deine Traumarbeit</h3>
|
||||
<ul className="list-disc list-inside text-sm space-y-2">
|
||||
{mockUserDreams.dreamRecommendations.forDreamWork.map((recommendation, index) => (
|
||||
<li key={index}>{recommendation}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="dreamy-card p-6" style={getBackgroundStyle('amber')}>
|
||||
<h3 className="text-lg font-bold mb-3 dreamy-text">Basierend auf deinem Profil</h3>
|
||||
<ul className="list-disc list-inside text-sm space-y-2">
|
||||
{mockUserDreams.dreamRecommendations.basedOnProfile.map((recommendation, index) => (
|
||||
<li key={index}>{recommendation}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
118
src/pages/dreamarchive/WorldwideEvents.tsx
Normal file
118
src/pages/dreamarchive/WorldwideEvents.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import {getBackgroundStyle, getTextStyle} from '../../styles/StyleUtils';
|
||||
import {FaFire, FaFlag, FaVirus} from 'react-icons/fa';
|
||||
import mockWorldwideEvents from '../../data/MockWorldwideEvents';
|
||||
import HeroSection from '../../components/dreamarchive/HeroSection';
|
||||
import SectionHeader from '../../components/dreamarchive/SectionHeader';
|
||||
|
||||
export default function WorldwideEvents() {
|
||||
return (<div className="p-4 pt-24 pb-20 max-w-6xl mx-auto relative overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<HeroSection
|
||||
containerTitle="Signifikante Ereignisse 2020-2025"
|
||||
description="Entdecke, wie weltweite Ereignisse wie die COVID-19 Pandemie, Klimawandel-Ereignisse und geopolitische Spannungen die Traumlandschaft beeinflusst haben."
|
||||
/>
|
||||
|
||||
{/* Interactive Timeline (Mock) */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Zeitlinie der Ereignisse"/>
|
||||
<div className="relative">
|
||||
<div
|
||||
className="absolute left-1/2 transform -translate-x-1/2 h-full w-1 bg-purple-300 dark:bg-purple-700 opacity-50"></div>
|
||||
|
||||
{/* Timeline Items */}
|
||||
<div className="relative z-10">
|
||||
{mockWorldwideEvents.timelineEvents.map((event, index) => {
|
||||
const isEven = index % 2 === 0;
|
||||
const isLast = index === mockWorldwideEvents.timelineEvents.length - 1;
|
||||
|
||||
return (
|
||||
<div key={index} className={`${!isLast ? 'mb-12' : ''} flex items-center`}>
|
||||
<div className="w-1/2 pr-8 text-right">
|
||||
{isEven ? (
|
||||
<>
|
||||
<h3 className="text-xl font-bold mb-2 dreamy-text">{event.year}</h3>
|
||||
<p className="text-sm" style={getTextStyle()}>{event.event}</p>
|
||||
</>
|
||||
) : (
|
||||
<div className="dreamy-card p-4">
|
||||
<p className="text-sm mb-2" style={getTextStyle()}>{event.dreamEffect}</p>
|
||||
<p className="text-xs"
|
||||
style={getTextStyle('muted')}>{event.dreamEffectDetail}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="absolute left-1/2 transform -translate-x-1/2 w-6 h-6 rounded-full"
|
||||
style={{background: 'var(--accent-gradient)'}}></div>
|
||||
<div className="w-1/2 pl-8">
|
||||
{isEven ? (
|
||||
<div className="dreamy-card p-4">
|
||||
<p className="text-sm mb-2" style={getTextStyle()}>{event.dreamEffect}</p>
|
||||
<p className="text-xs"
|
||||
style={getTextStyle('muted')}>{event.dreamEffectDetail}</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<h3 className="text-xl font-bold mb-2 dreamy-text">{event.year}</h3>
|
||||
<p className="text-sm" style={getTextStyle()}>{event.event}</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Detailed Event Sections */}
|
||||
<div className="mb-12">
|
||||
<SectionHeader title="Detaillierte Ereignisanalyse"/>
|
||||
|
||||
{mockWorldwideEvents.detailedEvents.map((event, index) => {
|
||||
// Dynamically determine which icon component to use
|
||||
let IconComponent;
|
||||
switch (event.icon) {
|
||||
case 'FaVirus':
|
||||
IconComponent = FaVirus;
|
||||
break;
|
||||
case 'FaFire':
|
||||
IconComponent = FaFire;
|
||||
break;
|
||||
case 'FaFlag':
|
||||
IconComponent = FaFlag;
|
||||
break;
|
||||
default:
|
||||
IconComponent = FaVirus;
|
||||
}
|
||||
|
||||
const isLast = index === mockWorldwideEvents.detailedEvents.length - 1;
|
||||
|
||||
return (
|
||||
<div key={event.id} className={`dreamy-card ${!isLast ? 'mb-8' : ''} p-6`}
|
||||
style={getBackgroundStyle(event.color as 'purple' | 'blue' | 'violet' | 'emerald' | 'amber' | 'rose' | 'pink-red' | 'cta')}>
|
||||
<div className="flex flex-col md:flex-row items-center mb-4">
|
||||
<div className={`p-3 bg-${event.color}-500/20 rounded-full mb-4 md:mb-0 md:mr-4`}>
|
||||
<IconComponent className={`text-${event.color}-600 dark:text-${event.color}-400`}
|
||||
size={32}/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold dreamy-text">{event.title}</h3>
|
||||
</div>
|
||||
|
||||
<div className={`grid grid-cols-1 md:grid-cols-${event.details.length} gap-4 mb-4`}>
|
||||
{event.details.map((detail, detailIndex) => (
|
||||
<div key={detailIndex} className="bg-white/20 dark:bg-black/20 p-4 rounded-lg">
|
||||
<h4 className="font-bold mb-2">{detail.title}</h4>
|
||||
<p className="text-sm">{detail.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-sm">
|
||||
{event.summary}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
135
src/styles/StyleUtils.ts
Normal file
135
src/styles/StyleUtils.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Utility functions for consistent styling across components
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the base style for dreamy cards
|
||||
* @param floating - Whether the card should have a floating animation
|
||||
* @returns Object with style properties
|
||||
*/
|
||||
export const getCardStyle = (floating: boolean = false) => {
|
||||
return {
|
||||
backgroundColor: 'var(--card)',
|
||||
color: 'var(--text)',
|
||||
className: `dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01] ${floating ? 'floating' : ''}`
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the style for accent-colored elements
|
||||
* @param soft - Whether to use the soft accent color
|
||||
* @param isActive - Whether the element is in active state
|
||||
* @returns Object with style properties
|
||||
*/
|
||||
export const getAccentStyle = (soft: boolean = false, isActive: boolean = true) => {
|
||||
if (!isActive) {
|
||||
return {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--text)'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundColor: soft ? 'var(--accent-soft)' : 'var(--accent)',
|
||||
color: soft ? 'var(--text)' : 'white'
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the style for text elements
|
||||
* @param type - The type of text (normal, muted, accent)
|
||||
* @returns Object with style properties
|
||||
*/
|
||||
export const getTextStyle = (type: 'normal' | 'muted' | 'accent' = 'normal') => {
|
||||
switch (type) {
|
||||
case 'muted':
|
||||
return {color: 'var(--text-muted)'};
|
||||
case 'accent':
|
||||
return {color: 'var(--accent)'};
|
||||
default:
|
||||
return {color: 'var(--text)'};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the style for background elements
|
||||
* @param type - The type of background (normal, card, gradient)
|
||||
* @returns Object with style properties
|
||||
*/
|
||||
export const getBackgroundStyle = (
|
||||
type: 'normal' | 'card' | 'gradient' | 'accent-gradient' | 'topbar' |
|
||||
'purple' | 'blue' | 'violet' | 'emerald' | 'amber' | 'rose' | 'pink-red' | 'cta' = 'normal'
|
||||
) => {
|
||||
switch (type) {
|
||||
case 'card':
|
||||
return {backgroundColor: 'var(--bg)', boxShadow: '0 4px 15px var(--shadow)'};
|
||||
case 'gradient':
|
||||
return {
|
||||
background: 'linear-gradient(135deg, var(--accent), var(--accent-dark))',
|
||||
color: 'white',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3)'
|
||||
};
|
||||
case 'accent-gradient':
|
||||
return {
|
||||
background: 'var(--accent-gradient)',
|
||||
color: 'white',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3)'
|
||||
};
|
||||
case 'topbar':
|
||||
return {
|
||||
background: 'var(--accent-gradient)',
|
||||
boxShadow: '0 2px 10px var(--shadow)',
|
||||
backdropFilter: 'blur(10px)'
|
||||
};
|
||||
case 'purple':
|
||||
return {
|
||||
background: 'var(--purple-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.2)'
|
||||
};
|
||||
case 'blue':
|
||||
return {
|
||||
background: 'var(--blue-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(59, 130, 246, 0.2)'
|
||||
};
|
||||
case 'violet':
|
||||
return {
|
||||
background: 'var(--violet-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(139, 92, 246, 0.2)'
|
||||
};
|
||||
case 'emerald':
|
||||
return {
|
||||
background: 'var(--emerald-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(16, 185, 129, 0.2)'
|
||||
};
|
||||
case 'amber':
|
||||
return {
|
||||
background: 'var(--amber-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(245, 158, 11, 0.2)'
|
||||
};
|
||||
case 'rose':
|
||||
return {
|
||||
background: 'var(--rose-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(244, 63, 94, 0.2)'
|
||||
};
|
||||
case 'pink-red':
|
||||
return {
|
||||
background: 'var(--pink-red-gradient)',
|
||||
color: 'var(--text)',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(236, 72, 153, 0.2)'
|
||||
};
|
||||
case 'cta':
|
||||
return {
|
||||
background: 'var(--cta-gradient)',
|
||||
color: 'white',
|
||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(236, 72, 153, 0.3)'
|
||||
};
|
||||
default:
|
||||
return {backgroundColor: 'var(--bg)'};
|
||||
}
|
||||
};
|
@@ -16,12 +16,27 @@ export type AudioInput = {
|
||||
transcript: string;
|
||||
}
|
||||
|
||||
export type ChipInput = {
|
||||
inputType: "chip";
|
||||
text: string;
|
||||
eeg: {
|
||||
alpha: number[];
|
||||
beta: number[];
|
||||
theta: number[];
|
||||
delta: number[];
|
||||
}
|
||||
puls: number[];
|
||||
hrv: number[];
|
||||
bewegung: number[];
|
||||
}
|
||||
|
||||
export default class Dream{
|
||||
id: number;
|
||||
userId: number;
|
||||
title: string;
|
||||
date: Date;
|
||||
input: TextInput | ImageInput | AudioInput;
|
||||
tags: string[];
|
||||
input: TextInput | ImageInput | AudioInput | ChipInput;
|
||||
ai?:{
|
||||
interpretation: string;
|
||||
image?: string;
|
||||
@@ -29,13 +44,17 @@ export default class Dream{
|
||||
video?: string;
|
||||
models?: string;
|
||||
}
|
||||
vr?: {
|
||||
models: never;
|
||||
}
|
||||
|
||||
constructor(params: {
|
||||
id: number;
|
||||
userId: number;
|
||||
title: string;
|
||||
date: Date;
|
||||
input: TextInput | ImageInput | AudioInput;
|
||||
tags: string[];
|
||||
input: TextInput | ImageInput | AudioInput | ChipInput;
|
||||
ai: {
|
||||
interpretation: string;
|
||||
image?: string;
|
||||
@@ -48,6 +67,7 @@ export default class Dream{
|
||||
this.userId = params.userId;
|
||||
this.title = params.title;
|
||||
this.date = params.date;
|
||||
this.tags = params.tags;
|
||||
this.input = params.input;
|
||||
this.ai= params.ai;
|
||||
}
|
||||
|
54
src/utils/DateUtils.ts
Normal file
54
src/utils/DateUtils.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Utility functions for date formatting
|
||||
*/
|
||||
|
||||
/**
|
||||
* Formats a date with full details including weekday and month names
|
||||
* @param date - The date to format
|
||||
* @returns Formatted date string (e.g., "Montag, 1. Januar 2023")
|
||||
*/
|
||||
export const formatDateFull = (date: Date): string => {
|
||||
return date.toLocaleDateString('de-DE', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a date in a simple format
|
||||
* @param date - The date to format
|
||||
* @returns Formatted date string (e.g., "01.01.2023")
|
||||
*/
|
||||
export const formatDateSimple = (date: Date): string => {
|
||||
return date.toLocaleDateString('de-DE');
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a date with time
|
||||
* @param date - The date to format
|
||||
* @returns Formatted date and time string (e.g., "01.01.2023, 14:30")
|
||||
*/
|
||||
export const formatDateWithTime = (date: Date): string => {
|
||||
return date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a date in a numeric format without time
|
||||
* @param date - The date to format
|
||||
* @returns Formatted date string (e.g., "01.01.2023")
|
||||
*/
|
||||
export const formatDateNumeric = (date: Date): string => {
|
||||
return date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
});
|
||||
};
|
@@ -1,4 +1,4 @@
|
||||
import Dream from '../types/Dream';
|
||||
import Dream from '../types/Dream.ts';
|
||||
|
||||
/**
|
||||
* Sorts dreams by date in descending order (newest first)
|
@@ -8,4 +8,34 @@ export default defineConfig({
|
||||
react(),
|
||||
tailwindcss()
|
||||
],
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
// Group Three.js related libraries
|
||||
'three-bundle': [
|
||||
'three',
|
||||
'@react-three/fiber',
|
||||
'@react-three/drei',
|
||||
'three-stdlib'
|
||||
],
|
||||
// D3 visualization library
|
||||
'd3': ['d3'],
|
||||
// Slider related libraries
|
||||
'slider': [
|
||||
'react-slick',
|
||||
'slick-carousel'
|
||||
],
|
||||
// React and related libraries
|
||||
'react-vendor': [
|
||||
'react',
|
||||
'react-dom',
|
||||
'react-router-dom'
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// Increase the warning limit to avoid unnecessary warnings
|
||||
chunkSizeWarningLimit: 1000
|
||||
}
|
||||
})
|
||||
|
Reference in New Issue
Block a user