refactor: separate components into folders

This commit is contained in:
2026-02-04 16:16:28 +05:00
parent 1123e1fcce
commit 79c4d00c30
18 changed files with 187 additions and 33 deletions
+72
View File
@@ -0,0 +1,72 @@
<script lang="ts">
import AppHeader from "./AppHeader.svelte";
import ErrorMessage from "../feedback/ErrorMessage.svelte";
import AppContent from "./AppContent.svelte";
interface Props {
errorMessage: string | undefined;
uploadedImage: string | undefined;
texts: Array<{ id: string; text: string }>;
backgroundImage: string | undefined;
panels: any[];
onUploadNewImage: () => void;
onImageUpload: (image: string) => void;
onCropComplete: (croppedImage: string) => void;
onCropCancel: () => void;
onTextAdd: (text: string) => void;
onTextUpdate: (id: string, newText: string) => void;
onTextDelete: (id: string) => void;
onDownload: (panel: any) => Promise<void>;
onDownloadAll: () => Promise<void>;
}
let {
errorMessage,
uploadedImage,
texts,
backgroundImage,
panels,
onUploadNewImage,
onImageUpload,
onCropComplete,
onCropCancel,
onTextAdd,
onTextUpdate,
onTextDelete,
onDownload,
onDownloadAll,
}: Props = $props();
</script>
<div class="app-container">
<AppHeader {onUploadNewImage} />
<ErrorMessage {errorMessage} />
<AppContent
{uploadedImage}
{texts}
{backgroundImage}
{panels}
{onImageUpload}
{onCropComplete}
{onCropCancel}
{onTextAdd}
{onTextUpdate}
{onTextDelete}
{onUploadNewImage}
{onDownload}
{onDownloadAll}
/>
</div>
<style>
.app-container {
display: flex;
flex-direction: column;
gap: 1.5rem;
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
}
</style>
+64
View File
@@ -0,0 +1,64 @@
<script lang="ts">
import MainSection from "./MainSection.svelte";
import Sidebar from "./Sidebar.svelte";
interface Props {
uploadedImage: string | undefined;
texts: Array<{ id: string; text: string }>;
backgroundImage: string | undefined;
panels: any[];
onImageUpload: (image: string) => void;
onCropComplete: (croppedImage: string) => void;
onCropCancel: () => void;
onTextAdd: (text: string) => void;
onTextUpdate: (id: string, newText: string) => void;
onTextDelete: (id: string) => void;
onUploadNewImage: () => void;
onDownload: (panel: any) => Promise<void>;
onDownloadAll: () => Promise<void>;
}
let {
uploadedImage,
texts,
backgroundImage,
panels,
onImageUpload,
onCropComplete,
onCropCancel,
onTextAdd,
onTextUpdate,
onTextDelete,
onUploadNewImage,
onDownload,
onDownloadAll,
}: Props = $props();
</script>
<div class="app-content">
<MainSection
{uploadedImage}
{texts}
{onImageUpload}
{onCropComplete}
{onCropCancel}
{onTextAdd}
{onTextUpdate}
{onTextDelete}
/>
<Sidebar {backgroundImage} {panels} {onUploadNewImage} {onDownload} {onDownloadAll} />
</div>
<style>
.app-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
@media (max-width: 1024px) {
.app-content {
grid-template-columns: 1fr;
}
}
</style>
+35
View File
@@ -0,0 +1,35 @@
<script lang="ts">
import { Button } from "$lib/components/ui";
interface Props {
onUploadNewImage?: () => void;
}
let { onUploadNewImage }: Props = $props();
</script>
<div class="app-header">
<h1>Twitch Panels Creator</h1>
{#if onUploadNewImage}
<Button variant="primary" onclick={onUploadNewImage}>Загрузить изображение</Button>
{/if}
</div>
<style>
.app-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
color: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.app-header h1 {
margin: 0;
font-size: 2rem;
font-weight: 600;
}
</style>
+42
View File
@@ -0,0 +1,42 @@
<script lang="ts">
import { uiStore } from "../../stores/uiStore";
import ImageManager from "../image/ImageManager.svelte";
import TextSection from "../text/TextSection.svelte";
interface Props {
uploadedImage: string | undefined;
texts: Array<{ id: string; text: string }>;
onImageUpload: (image: string) => void;
onCropComplete: (croppedImage: string) => void;
onCropCancel: () => void;
onTextAdd: (text: string) => void;
onTextUpdate: (id: string, newText: string) => void;
onTextDelete: (id: string) => void;
}
let {
uploadedImage,
texts,
onImageUpload,
onCropComplete,
onCropCancel,
onTextAdd,
onTextUpdate,
onTextDelete,
}: Props = $props();
</script>
<div class="main-section">
<ImageManager currentStep={$uiStore.currentStep} {uploadedImage} {onImageUpload} {onCropComplete} {onCropCancel} />
{#if $uiStore.currentStep === "text"}
<TextSection {texts} {onTextAdd} {onTextUpdate} {onTextDelete} />
{/if}
</div>
<style>
.main-section {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
</style>
+36
View File
@@ -0,0 +1,36 @@
<script lang="ts">
import { uiStore } from "../../stores/uiStore";
import BackgroundPreview from "../image/BackgroundPreview.svelte";
import PanelsList from "../panel/PanelsList.svelte";
interface Props {
backgroundImage: string | undefined;
panels: any[];
onUploadNewImage: () => void;
onDownload: (panel: any) => Promise<void>;
onDownloadAll: () => Promise<void>;
}
let { backgroundImage, panels, onUploadNewImage, onDownload, onDownloadAll }: Props = $props();
</script>
<div class="sidebar">
{#if $uiStore.currentStep === "text"}
<BackgroundPreview {backgroundImage} {onUploadNewImage} />
<PanelsList {panels} {onDownload} {onDownloadAll} />
{/if}
</div>
<style>
.sidebar {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
@media (max-width: 1024px) {
.sidebar {
order: -1;
}
}
</style>