एक आधुनिक वेब एप्लिकेशन को कैसे संरचित किया जाए? यह कैसे सुनिश्चित किया जाए कि यह समय के साथ रखरखाव योग्य रहे? इस गाइड में, हम हेक्सागोनल आर्किटेक्चर और मजबूत फॉर्म वैलिडेशन का उपयोग करके एक Next.js एप्लिकेशन बनाएंगे। सीखने को और मजेदार बनाने के लिए, हम एक जेडाई अकादमी पंजीकरण सिस्टम बनाएंगे!
सोर्स कोड GitHub पर उपलब्ध है।
विषय-सूची
- हेक्सागोनल आर्किटेक्चर का परिचय
- इंस्टॉलेशन और संरचना
- डोमेन
- इन्फ्रास्ट्रक्चर
- यूजर इंटरफेस
- आगे की राह
1. हेक्सागोनल आर्किटेक्चर का परिचय
1.1 हेक्सागोनल आर्किटेक्चर क्या है?
हेक्सागोनल आर्किटेक्चर, जिसे "पोर्ट्स एंड एडाप्टर्स" भी कहा जाता है, एक आर्किटेक्चरल पैटर्न है जो ऐसे एप्लिकेशन बनाने की अनुमति देता है जहां बिजनेस कंपोनेंट्स हैं:
- तकनीकी विवरणों से अलग
- अलग-अलग टेस्ट करने योग्य
- उपयोग किए गए फ्रेमवर्क से स्वतंत्र
आर्किटेक्चर तीन मुख्य परतों में विभाजित है:
- डोमेन: शुद्ध बिजनेस लॉजिक रखता है
- पोर्ट्स: डोमेन के साथ संवाद करने के लिए इंटरफेस परिभाषित करते हैं
- एडाप्टर्स: बाहरी दुनिया के साथ इंटरैक्ट करने के लिए पोर्ट्स को लागू करते हैं
1.2 हेक्सागोनल आर्किटेक्चर का उपयोग क्यों करें?
लाभ
- स्पष्ट कार्यों का विभाजन
- सुरक्षित और केंद्रीकृत बिजनेस लॉजिक
- सरल टेस्टिंग
- तकनीकों को बदलने की लचीलापन
- सरल रखरखाव
आदर्श उपयोग के मामले
- जटिल बिजनेस नियमों वाले एप्लिकेशन
- समय के साथ विकसित होने वाले प्रोजेक्ट
- उच्च टेस्टेबिलिटी की आवश्यकता वाले सिस्टम
- कई इंटरफेस का समर्थन करने वाले एप्लिकेशन
[सामग्री जारी है...]
2. इंस्टॉलेशन और संरचना
2.1 पूर्ण इंस्टॉलेशन
bash
1# प्रोजेक्ट बनाना
2npx create-next-app@latest jedi-academy
प्रोजेक्ट बनाते समय, निम्नलिखित प्रश्नों का उत्तर दें:
Would you like to use TypeScript? Yes
Would you like to use ESLint? Yes
Would you like to use Tailwind CSS? Yes
Would you like to use `src/` directory? Yes
Would you like to use App Router? (recommended) Yes
Would you like to customize the default import alias (@/*)? Yes
Using Next.js version 15.0.0+ with Turbopack
प्रोजेक्ट बनने के बाद, डिपेंडेंसी इंस्टॉल करें:
bash
1cd jedi-academy
2
3# फॉर्म प्रबंधन और वैलिडेशन के लिए मुख्य डिपेंडेंसी
4npm install @hookform/resolvers zod react-hook-form
5
6# प्रिज़्मा डेटाबेस
7npm install @prisma/client
8npm install -D prisma
9
10# shadcn/ui इंस्टॉलेशन
11npx shadcn@latest init
shadcn/ui को इनिशियलाइज़ करते समय, निम्नलिखित प्रश्नों का उत्तर दें:
Would you like to use TypeScript (recommended)? Yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › src/app/globals.css
Would you like to use CSS variables for colors? › Yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › Yes
# आवश्यक कंपोनेंट्स इंस्टॉल करें
npx shadcn@latest add form input select textarea button card toast table
bash
1# दिनांक उपयोगिताएं
2npm install date-fns
3
4# डेटाबेस
5npx prisma init --datasource-provider sqlite
2.2 प्रोजेक्ट संरचना
src/
├── app/
│ ├── actions/
│ │ └── register-padawan.ts
│ ├── components/
│ │ ├── ui/ # shadcn/ui कंपोनेंट्स
│ │ ├── jedi-form.tsx
│ │ └── padawan-list.tsx
│ ├── lib/
│ │ └── utils.ts # shadcn/ui उपयोगिताएं
│ └── page.tsx
├── core/
│ ├── domain/
│ │ ├── models/
│ │ │ └── padawan.ts
│ │ ├── ports/
│ │ │ └── padawan-repository.ts
│ │ ├── services/
│ │ │ └── padawan-eligibility.ts
│ │ ├── validation/
│ │ │ └── padawan-schema.ts
│ │ └── events/
│ │ └── padawan-registered.ts
│ └── usecases/
│ └── register-padawan.ts
└── infrastructure/
└── db/
├── prisma/
│ ├── migrations/
│ └── schema.prisma
├── prisma.ts
└── repositories/
└── prisma-padawan-repository.ts
यह संरचना एक स्पष्ट हेक्सागोनल आर्किटेक्चर का पालन करती है:
app/
- Next.js यूजर इंटरफेस लेयर
actions/
- फॉर्म हैंडलिंग के लिए सर्वर एक्शन्स
components/
- UI/बिजनेस सेपरेशन के साथ React कंपोनेंट्स
lib/
- शेयर्ड उपयोगिताएं
core/
- शुद्ध बिजनेस लॉजिक
domain/
- मॉडल्स, पोर्ट्स और बिजनेस सर्विसेज
usecases/
- एप्लिकेशन यूज केसेज
infrastructure/
- तकनीकी कार्यान्वयन
db/
- प्रिज़्मा कॉन्फिगरेशन और रिपॉजिटरी कार्यान्वयन
3. डोमेन: एप्लिकेशन का मूल
3.1 डोमेन को समझना
डोमेन हमारे एप्लिकेशन का हृदय है। यहीं हम बिजनेस नियमों को किसी भी तकनीकी विचार से स्वतंत्र रूप से कोड में बदलते हैं। हमारे मामले में, डोमेन जेडाई अकादमी में पंजीकरण को नियंत्रित करने वाले सभी नियमों का प्रतिनिधित्व करता है।
प्रमुख डोमेन सिद्धांत
- तकनीकी स्वतंत्रता
- कोई फ्रेमवर्क डिपेंडेंसी नहीं
- कोई पर्सिस्टेंस-संबंधित कोड नहीं
- कोई UI लॉजिक नहीं
- केंद्रीकृत बिजनेस नियम
- सभी बिजनेस लॉजिक डोमेन में है
- नियम स्पष्ट और प्रलेखित हैं
- बिजनेस वैलिडेशन तकनीकी वैलिडेशन से अलग हैं
- समृद्ध मॉडलिंग
- सटीक टाइप्स और इंटरफेस का उपयोग
- महत्वपूर्ण बिजनेस अवधारणाओं के लिए वैल्यू ऑब्जेक्ट्स
- स्पष्ट पहचान वाली एंटिटीज
3.2 डोमेन कंपोनेंट्स
3.2.1 मॉडल्स
मॉडल्स मौलिक बिजनेस अवधारणाओं का प्रतिनिधित्व करते हैं।
typescript
1// src/core/domain/models/padawan.ts
2export type PrimarySkill = "combat" | "healing" | "meditation" | "telepathy";
3
4export interface Padawan {
5 id?: string;
6 name: string;
7 age: number;
8 midichlorianCount: number;
9 homeworld: string;
10 primarySkill: PrimarySkill;
11 background: string;
12 createdAt?: Date;
13}
14
15export class Result<T> {
16 private constructor(
17 private readonly _isSuccess: boolean,
18 private readonly value?: T,
19 private readonly error?: string
20 ) {}
21
22 static success<T>(value: T): Result<T> {
23 return new Result<T>(true, value);
24 }
25
26 static failure<T>(error: string): Result<T> {
27 return new Result<T>(false, undefined, error);
28 }
29
30 getError(): string | undefined {
31 return this.error;
32 }
33
34 getValue(): T | undefined {
35 return this.value;
36 }
37
38 isSuccess(): boolean {
39 return this._isSuccess;
40 }
41}
3.2.2 डोमेन इवेंट्स
इवेंट्स डोमेन में घटित महत्वपूर्ण तथ्यों का प्रतिनिधित्व करते हैं।
typescript
1// src/core/domain/events/padawan-registered.ts
2export interface DomainEvent {
3 occurredOn: Date;
4}
5
6export class PadawanRegistered implements DomainEvent {
7 occurredOn: Date = new Date();
8
9 constructor(
10 public readonly padawanId: string,
11 public readonly name: string,
12 public readonly midichlorianCount: number
13 ) {}
14}
3.2.3 पोर्ट्स (इंटरफेस)
पोर्ट्स परिभाषित करते हैं कि डोमेन बाहरी दुनिया के साथ कैसे संवाद करता है।
typescript
1// src/core/domain/ports/padawan-repository.ts
2import { Padawan, Result } from "@/core/domain/models/padawan";
3
4export interface PadawanRepository {
5 save(padawan: Omit<Padawan, "id" | "createdAt">): Promise<Result<Padawan>>;
6 findById(id: string): Promise<Result<Padawan | null>>;
7 findAll(): Promise<Result<Padawan[]>>;
8}
3.2.4 डोमेन सर्विसेज
डोमेन सर्विसेज बिजनेस लॉजिक को एनकैप्सुलेट करती हैं जो स्वाभाविक रूप से एक एंटिटी में फिट नहीं होती।
typescript
1// src/core/domain/services/padawan-eligibility.ts
2import { Padawan, Result } from "@/core/domain/models/padawan";
3
4export class PadawanEligibilityService {
5 static check(padawan: Omit<Padawan, "id" | "createdAt">): Result<void> {
6 if (padawan.age < 4) {
7 return Result.failure("प्रशिक्षण शुरू करने के लिए बहुत छोटे हैं");
8 }
9 if (padawan.age > 30) {
10 return Result.failure("प्रशिक्षण शुरू करने के लिए बहुत बड़े हैं");
11 }
12
13 if (padawan.midichlorianCount < 7000) {
14 return Result.failure("मिडिक्लोरियन काउंट जेडाई प्रशिक्षण के लिए बहुत कम है");
15 }
16 if (padawan.midichlorianCount > 20000) {
17 return Result.failure("संदिग्ध मिडिक्लोरियन काउंट");
18 }
19
20 if (padawan.background.length < 20) {
21 return Result.failure("व्यक्तिगत कहानी में अधिक विवरण की आवश्यकता है");
22 }
23
24 return Result.success(void 0);
25 }
26}
3.2.5 यूज केसेज
यूज केसेज एक बिजनेस कार्यक्षमता को प्राप्त करने के लिए विभिन्न डोमेन तत्वों के बीच इंटरैक्शन को व्यवस्थित करते हैं।
typescript
1// src/core/usecases/register-padawan.ts
2import { Padawan, Result } from "@/core/domain/models/padawan";
3import { PadawanRepository } from "@/core/domain/ports/padawan-repository";
4import { PadawanEligibilityService } from "@/core/domain/services/padawan-eligibility";
5import { PadawanRegistered } from "@/core/domain/events/padawan-registered";
6import { EventDispatcher } from "@/core/domain/ports/event-dispatcher";
7
8export class RegisterPadawanUseCase {
9 constructor(
10 private readonly padawanRepository: PadawanRepository,
11 private readonly eventDispatcher: EventDispatcher
12 ) {}
13
14 async execute(
15 padawan: Omit<Padawan, "id" | "createdAt">
16 ): Promise<Result<Padawan>> {
17 const eligibilityResult = PadawanEligibilityService.check(padawan);
18 if (!eligibilityResult.isSuccess()) {
19 return Result.failure(eligibilityResult.getError()!);
20 }
21
22 const saveResult = await this.padawanRepository.save(padawan);
23 if (!saveResult.isSuccess()) {
24 return Result.failure(saveResult.getError()!);
25 }
26
27 const savedPadawan = saveResult.getValue()!;
28
29 await this.eventDispatcher.dispatch(
30 new PadawanRegistered(
31 savedPadawan.id!,
32 savedPadawan.name,
33 savedPadawan.midichlorianCount
34 )
35 );
36
37 return Result.success(savedPadawan);
38 }
39}
4. इन्फ्रास्ट्रक्चर
इन्फ्रास्ट्रक्चर बाहरी दुनिया के साथ इंटरैक्ट करने के लिए डोमेन में परिभाषित पोर्ट्स को लागू करता है।
4.1 प्रिज़्मा कॉन्फिगरेशन
prisma
1// prisma/schema.prisma
2generator client {
3 provider = "prisma-client-js"
4}
5
6datasource db {
7 provider = "sqlite"
8 url = env("DATABASE_URL")
9}
10
11model Padawan {
12 id String @id @default(uuid())
13 name String
14 age Int
15 midichlorianCount Int
16 homeworld String
17 primarySkill String
18 background String
19 createdAt DateTime @default(now())
20
21 @@map("padawans")
22}
4.2 एडाप्टर कार्यान्वयन
typescript
1// src/infrastructure/db/repositories/prisma-padawan-repository.ts
2import { Padawan, Result } from "@/core/domain/models/padawan";
3import { PadawanRepository } from "@/core/domain/ports/padawan-repository";
4import { prisma } from "@/infrastructure/db/prisma";
5
6export class PrismaPadawanRepository implements PadawanRepository {
7 async save(
8 padawan: Omit<Padawan, "id" | "createdAt">
9 ): Promise<Result<Padawan>> {
10 try {
11 const saved = await prisma.padawan.create({
12 data: padawan,
13 });
14
15 return Result.success(this.mapPrismaPadawanToDomain(saved));
16 } catch (error: unknown) {
17 if (error instanceof Error) {
18 return Result.failure(`सेव के दौरान त्रुटि: ${error.message}`);
19 }
20 return Result.failure('सेव के दौरान एक अज्ञात त्रुटि हुई');
21 }
22 }
23
24 async findById(id: string): Promise<Result<Padawan | null>> {
25 try {
26 const padawan = await prisma.padawan.findUnique({
27 where: { id },
28 });
29
30 return Result.success(
31 padawan ? this.mapPrismaPadawanToDomain(padawan) : null
32 );
33 } catch (error: unknown) {
34 if (error instanceof Error) {
35 return Result.failure(`खोज के दौरान त्रुटि: ${error.message}`);
36 }
37 return Result.failure('खोज के दौरान एक अज्ञात त्रुटि हुई');
38 }
39 }
40
41 async findAll(): Promise<Result<Padawan[]>> {
42 try {
43 const padawans = await prisma.padawan.findMany({
44 orderBy: { createdAt: "desc" },
45 });
46
47 return Result.success(padawans.map(this.mapPrismaPadawanToDomain));
48 } catch (error: unknown) {
49 if (error instanceof Error) {
50 return Result.failure(`पुनर्प्राप्ति के दौरान त्रुटि: ${error.message}`);
51 }
52 return Result.failure('पुनर्प्राप्ति के दौरान एक अज्ञात त्रुटि हुई');
53 }
54 }
55
56 private mapPrismaPadawanToDomain(padawan: any): Padawan {
57 return {
58 id: padawan.id,
59 name: padawan.name,
60 age: padawan.age,
61 midichlorianCount: padawan.midichlorianCount,
62 homeworld: padawan.homeworld,
63 primarySkill: padawan.primarySkill,
64 background: padawan.background,
65 createdAt: padawan.createdAt,
66 };
67 }
68}
5. यूजर इंटरफेस
5.1 Zod के साथ वैलिडेशन
इनपुट डेटा वैलिडेशन हमारे डोमेन के साथ संगतता सुनिश्चित करने के लिए Zod का उपयोग करता है।
typescript
1// src/core/domain/validation/padawan-schema.ts
2import { z } from "zod";
3
4export const padawanSchema = z.object({
5 name: z
6 .string()
7 .min(2, "पैडवन का नाम 2 अक्षरों से लंबा होना चाहिए")
8 .max(50, "क्वाई-गॉन जिन का भी इतना लंबा नाम नहीं है"),
9 age: z.coerce
10 .number()
11 .min(4, "ग्रोगू ने भी 4 साल की उम्र में प्रशिक्षण शुरू किया")
12 .max(30, "परिषद इस उम्र को प्रशिक्षण शुरू करने की सीमा मानती है"),
13 midichlorianCount: z.coerce
14 .number()
15 .min(7000, "जेडाई प्रशिक्षण के लिए मिडिक्लोरियन काउंट बहुत कम है")
16 .max(20000, "एनाकिन के पास भी केवल 20000 मिडिक्लोरियन थे"),
17 homeworld: z
18 .string()
19 .min(2, "आपके ग्रह का नाम आवश्यक है"),
20 primarySkill: z.enum(["combat", "healing", "meditation", "telepathy"], {
21 errorMap: () => ({
22 message: "यह कौशल जेडाई आदेश द्वारा मान्यता प्राप्त नहीं है",
23 }),
24 }),
25 background: z
26 .string()
27 .min(20, "हमें आपकी यात्रा के बारे में और बताएं"),
28});
29
30export type PadawanFormData = z.infer<typeof padawanSchema>;
अब हम डेटाबेस जनरेट कर सकते हैं।
आगे की खोज के लिए, प्रिज़्मा डेटाबेस को विज़ुअलाइज़ करने के लिए एक क्लाइंट प्रदान करता है।
5.2 पंजीकरण के लिए सर्वर एक्शन
typescript
1// src/app/actions/register-padawan.ts
2'use server'
3
4import { PrismaPadawanRepository } from '@/infrastructure/db/repositories/prisma-padawan-repository';
5import { ConsoleEventDispatcher } from '@/infrastructure/services/event-dispatcher';
6import { RegisterPadawanUseCase } from '@/core/usecases/register-padawan';
7import { padawanSchema } from '@/core/domain/validation/padawan-schema';
8import { revalidatePath } from 'next/cache';
9
10const padawanRepository = new PrismaPadawanRepository();
11const eventDispatcher = new ConsoleEventDispatcher();
12const registerPadawan = new RegisterPadawanUseCase(
13 padawanRepository,
14 eventDispatcher
15);
16
17export async function handlePadawanRegistration(formData: FormData) {
18 try {
19 const validatedData = padawanSchema.parse(Object.fromEntries(formData));
20 const result = await registerPadawan.execute(validatedData);
21
22 if (!result.isSuccess()) {
23 return {
24 success: false,
25 message: result.getError()
26 };
27 }
28
29 revalidatePath('/');
30 return {
31 success: true,
32 message: "फोर्स आपके साथ हो, युवा पैडवन! 🌟"
33 };
34 } catch (error) {
35 return {
36 success: false,
37 message: "फोर्स में एक गड़बड़ी का पता चला है... 🌀"
38 };
39 }
40}
5.3 फॉर्म कंपोनेंट
typescript
1// src/app/components/jedi-form.tsx
2"use client";
3
4import { useForm } from "react-hook-form";
5import { zodResolver } from "@hookform/resolvers/zod";
6import { useToast } from "@/hooks/use-toast";
7
8import {
9 Form,
10 FormControl,
11 FormField,
12 FormItem,
13 FormLabel,
14 FormMessage,
15} from "@/components/ui/form";
16import {
17 Card,
18 CardHeader,
19 CardTitle,
20 CardDescription,
21 CardContent,
22} from "@/components/ui/card";
23import { Input } from "@/components/ui/input";
24import { Button } from "@/components/ui/button";
25import { Textarea } from "@/components/ui/textarea";
26import {
27 Select,
28 SelectContent,
29 SelectItem,
30 SelectTrigger,
31 SelectValue,
32} from "@/components/ui/select";
33import {
34 padawanSchema,
35 type PadawanFormData,
36} from "@/core/domain/validation/padawan-schema";
37import { handlePadawanRegistration } from "../actions/register-padawan";
38
39export function JediRegistrationForm() {
40 const { toast } = useToast();
41 const form = useForm<PadawanFormData>({
42 resolver: zodResolver(padawanSchema),
43 defaultValues: {
44 name: "",
45 age: 0,
46 midichlorianCount: 7000,
47 homeworld: "",
48 primarySkill: "combat",
49 background: "",
50 },
51 });
52
53 async function onSubmit(data: PadawanFormData) {
54 const formData = new FormData();
55 Object.entries(data).forEach(([key, value]) => {
56 formData.append(key, value.toString());
57 });
58
59 const result = await handlePadawanRegistration(formData);
60
61 toast({
62 title: result.success ? "पंजीकरण सफल" : "त्रुटि",
63 description: result.message,
64 variant: result.success ? "default" : "destructive",
65 });
66
67 if (result.success) {
68 form.reset();
69 }
70 }
71
72 return (
73 <Card className="w-full max-w-md mx-auto">
74 <CardHeader>
75 <CardTitle>जेडाई अकादमी</CardTitle>
76 <CardDescription>
77 आदेश में शामिल होने के लिए अपना आवेदन जमा करें
78 </CardDescription>
79 </CardHeader>
80 <CardContent>
81 <Form {...form}>
82 <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
83 <FormField
84 control={form.control}
85 name="name"
86 render={({ field }) => (
87 <FormItem>
88 <FormLabel>पैडवन का नाम</FormLabel>
89 <FormControl>
90 <Input placeholder="ल्यूक स्काईवॉकर" {...field} />
91 </FormControl>
92 <FormMessage />
93 </FormItem>
94 )}
95 />
96
97 <FormField
98 control={form.control}
99 name="age"
100 render={({ field }) => (
101 <FormItem>
102 <FormLabel>उम्र</FormLabel>
103 <FormControl>
104 <Input
105 type="number"
106 min="4"
107 max="30"
108 placeholder="19"
109 {...field}
110 onChange={(e) => field.onChange(parseInt(e.target.value))}
111 />
112 </FormControl>
113 <FormMessage />
114 </FormItem>
115 )}
116 />
117
118 <FormField
119 control={form.control}
120 name="midichlorianCount"
121 render={({ field }) => (
122 <FormItem>
123 <FormLabel>मिडिक्लोरियन काउंट</FormLabel>
124 <FormControl>
125 <Input
126 type="number"
127 min="7000"
128 max="20000"
129 step="100"
130 {...field}
131 onChange={(e) => field.onChange(parseInt(e.target.value))}
132 />
133 </FormControl>
134 <FormMessage />
135 </FormItem>
136 )}
137 />
138
139 <FormField
140 control={form.control}
141 name="homeworld"
142 render={({ field }) => (
143 <FormItem>
144 <FormLabel>गृह लोक</FormLabel>
145 <FormControl>
146 <Input placeholder="टैटूइन" {...field} />
147 </FormControl>
148 <FormMessage />
149 </FormItem>
150 )}
151 />
152
153 <FormField
154 control={form.control}
155 name="primarySkill"
156 render={({ field }) => (
157 <FormItem>
158 <FormLabel>प्राथमिक कौशल</FormLabel>
159 <Select
160 onValueChange={field.onChange}
161 defaultValue={field.value}
162 >
163 <FormControl>
164 <SelectTrigger>
165 <SelectValue placeholder="एक कौशल चुनें" />
166 </SelectTrigger>
167 </FormControl>
168 <SelectContent>
169 <SelectItem value="combat">
170 लाइटसेबर युद्ध ⚔️
171 </SelectItem>
172 <SelectItem value="healing">
173 फोर्स हीलिंग 💚
174 </SelectItem>
175 <SelectItem value="meditation">
176 गहन ध्यान 🧘
177 </SelectItem>
178 <SelectItem value="telepathy">टेलीपैथी 🧠</SelectItem>
179 </SelectContent>
180 </Select>
181 <FormMessage />
182 </FormItem>
183 )}
184 />
185
186 <FormField
187 control={form.control}
188 name="background"
189 render={({ field }) => (
190 <FormItem>
191 <FormLabel>आपकी कहानी</FormLabel>
192 <FormControl>
193 <Textarea
194 placeholder="हमें अपनी यात्रा के बारे में बताएं..."
195 className="resize-none"
196 rows={4}
197 {...field}
198 />
199 </FormControl>
200 <FormMessage />
201 </FormItem>
202 )}
203 />
204
205 <Button type="submit" className="w-full">
206 मेरा आवेदन जमा करें 🌟
207 </Button>
208 </form>
209 </Form>
210 </CardContent>
211 </Card>
212 );
213}
5.4 पैडवन सूची
typescript
1// src/app/components/padawan-list.tsx
2"use client";
3
4import {
5 Table,
6 TableBody,
7 TableCaption,
8 TableCell,
9 TableHead,
10 TableHeader,
11 TableRow,
12} from "@/components/ui/table";
13import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
14import { format } from "date-fns";
15import { enUS } from "date-fns/locale";
16import type { Padawan } from "@/core/domain/models/padawan";
17
18type PadawanListProps = {
19 padawans: Padawan[];
20};
21
22const skillEmoji = {
23 combat: "⚔️ लाइटसेबर युद्ध",
24 healing: "💚 फोर्स हीलिंग",
25 meditation: "🧘 गहन ध्यान",
26 telepathy: "🧠 टेलीपैथी",
27} as const;
28
29export function PadawanList({ padawans }: PadawanListProps) {
30 if (padawans.length === 0) {
31 return (
32 <Card>
33 <CardContent className="pt-6">
34 <p className="text-center text-muted-foreground">
35 अभी तक कोई पैडवन पंजीकृत नहीं...
36 </p>
37 </CardContent>
38 </Card>
39 );
40 }
41
42 return (
43 <Card>
44 <CardHeader>
45 <CardTitle>उम्मीदवारों की सूची</CardTitle>
46 </CardHeader>
47 <CardContent>
48 <Table>
49 <TableHeader>
50 <TableRow>
51 <TableHead>नाम</TableHead>
52 <TableHead>उम्र</TableHead>
53 <TableHead>गृह लोक</TableHead>
54 <TableHead>विशेषज्ञता</TableHead>
55 <TableHead>मिडिक्लोरियन</TableHead>
56 <TableHead>पंजीकरण</TableHead>
57 </TableRow>
58 </TableHeader>
59 <TableBody>
60 {padawans.map((padawan) => (
61 <TableRow key={padawan.id}>
62 <TableCell className="font-medium">{padawan.name}</TableCell>
63 <TableCell>{padawan.age} वर्ष</TableCell>
64 <TableCell>{padawan.homeworld}</TableCell>
65 <TableCell>{skillEmoji[padawan.primarySkill]}</TableCell>
66 <TableCell>
67 {padawan.midichlorianCount.toLocaleString()}
68 </TableCell>
69 <TableCell>
70 {format(new Date(padawan.createdAt!), "Pp", { locale: enUS })}
71 </TableCell>
72 </TableRow>
73 ))}
74 </TableBody>
75 </Table>
76 </CardContent>
77 </Card>
78 );
79}
ये कंपोनेंट्स एक आधुनिक और सुलभ यूजर इंटरफेस बनाने के लिए shadcn/ui का उपयोग करते हैं, जिसमें शामिल हैं:
- JediRegistrationForm:
- react-hook-form और Zod के साथ पूर्ण वैलिडेशन
- संदर्भित संदेशों के साथ त्रुटि प्रबंधन
- टोस्ट के साथ यूजर फीडबैक
- सफल सबमिशन के बाद फॉर्म रीसेट
- PadawanList:
- टेबुलर डेटा प्रदर्शन
- खाली स्थिति प्रबंधन
- अंग्रेजी में दिनांक फॉर्मेटिंग
- कौशल आइकन
- फॉर्म के साथ सुसंगत स्टाइलिंग
सब कुछ हमारे हेक्सागोनल आर्किटेक्चर में बिजनेस लॉजिक के बिना प्रेजेंटेशन लेयर पर रहते हुए पूरी तरह से एकीकृत होता है।
6. आगे की राह
6.1 तकनीकी सुधार
- कैश और प्रदर्शन
typescript
1// Redis कैश कार्यान्वयन उदाहरण
2export class RedisPadawanCache {
3 async cacheResults(key: string, data: any): Promise<void> {
4 await redis.set(key, JSON.stringify(data), "EX", 3600);
5 }
6}
- मॉनिटरिंग और लॉगिंग
typescript
1// मॉनिटरिंग सेवा
2export class ApplicationMonitoring {
3 trackDomainEvent(event: DomainEvent): void {
4 // मॉनिटरिंग सेवा को भेजें
5 }
6}
6.2 कार्यात्मक विकास
- अनुमोदन कार्यप्रवाह
- रेटिंग सिस्टम
- पदोन्नति प्रबंधन
- पैडवन संचार
निष्कर्ष
हेक्सागोनल आर्किटेक्चर ने हमें एक ऐसा एप्लिकेशन बनाने की अनुमति दी है जो है:
- रखरखाव योग्य
- कार्यों का स्पष्ट विभाजन
- अलग और सुरक्षित बिजनेस कोड
- स्केलेबल
- नई सुविधाएं जोड़ना आसान
- इन्फ्रास्ट्रक्चर बदलने की क्षमता
- नए इनपुट/आउटपुट चैनलों का समर्थन
आगे बढ़ने के लिए, आप कर सकते हैं:
- प्रमाणीकरण जोड़ें
- कैशिंग सिस्टम लागू करें
- मॉनिटरिंग सेट करें
- स्वचालित परीक्षण सेट करें
- वेबहुक जोड़ें
याद रखें: अच्छी आर्किटेक्चर फोर्स की तरह है - इसे संतुलन में होना चाहिए! 🌟
[अनुवाद समाप्त]