stuff
Some checks failed
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Mobile App CI / test (push) Has been cancelled
Web App CI / test (push) Has been cancelled
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
Mobile App CI / build-android (push) Has been cancelled
Mobile App CI / build-ios (push) Has been cancelled
Web App CI / build (push) Has been cancelled
Some checks failed
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Mobile App CI / test (push) Has been cancelled
Web App CI / test (push) Has been cancelled
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
Mobile App CI / build-android (push) Has been cancelled
Mobile App CI / build-ios (push) Has been cancelled
Web App CI / build (push) Has been cancelled
This commit is contained in:
parent
b4ad3598ee
commit
f6d68fb1fc
29 changed files with 1944 additions and 439 deletions
|
|
@ -112,7 +112,7 @@ export const cardsApi = {
|
|||
},
|
||||
|
||||
// Delete a card by ID
|
||||
deleteCard: async (cardId: string): Promise<{ success: boolean; message: string }> => {
|
||||
deleteCard: async (cardId: string): Promise<{ success: boolean; message?: string }> => {
|
||||
try {
|
||||
const response = await adminApiClient.delete(`/api/v2/admin/cards/${cardId}`)
|
||||
return response.data
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export const voicesApi = {
|
|||
removeCardVoice: async (
|
||||
cardId: string,
|
||||
voiceId: string
|
||||
): Promise<{ success: boolean }> => {
|
||||
): Promise<{ success: boolean; message?: string }> => {
|
||||
const response = await adminApiClient.delete(
|
||||
`/api/v2/admin/cards/${cardId}/voices/${voiceId}`
|
||||
)
|
||||
|
|
|
|||
214
mnemo_cards_admin/src/components/PackTestsManager.tsx
Normal file
214
mnemo_cards_admin/src/components/PackTestsManager.tsx
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { testsApi } from '@/api/tests'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Search, Check } from 'lucide-react'
|
||||
|
||||
interface PackTestsManagerProps {
|
||||
currentTestIds: string[]
|
||||
onTestsChange: (addIds: string[], removeIds: string[]) => void
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export function PackTestsManager({
|
||||
currentTestIds,
|
||||
onTestsChange,
|
||||
disabled = false,
|
||||
}: PackTestsManagerProps) {
|
||||
const [search, setSearch] = useState('')
|
||||
const [selectedTests, setSelectedTests] = useState<Set<string>>(new Set())
|
||||
const [removedTests, setRemovedTests] = useState<Set<string>>(new Set())
|
||||
|
||||
// Load all tests with search
|
||||
const { data: testsData, isLoading } = useQuery({
|
||||
queryKey: ['tests', 1, 100, search], // Limit to 100 (backend max)
|
||||
queryFn: () => testsApi.getTests({ page: 1, limit: 100, search }),
|
||||
enabled: !disabled,
|
||||
})
|
||||
|
||||
// Initialize selected tests from currentTestIds when it changes
|
||||
useEffect(() => {
|
||||
const initialSelected = new Set<string>(
|
||||
currentTestIds.filter((id) => !removedTests.has(id.toString()))
|
||||
)
|
||||
setSelectedTests(initialSelected)
|
||||
// Reset removed tests when currentTestIds changes (e.g., when opening dialog)
|
||||
setRemovedTests(new Set())
|
||||
}, [currentTestIds.join(',')]) // Use join to detect array changes
|
||||
|
||||
// Calculate which tests to add/remove when selection changes
|
||||
useEffect(() => {
|
||||
const currentlySelected = Array.from(selectedTests)
|
||||
const removed = Array.from(removedTests)
|
||||
|
||||
// Tests to add: selected but not in currentTestIds and not removed
|
||||
const toAdd = currentlySelected.filter(
|
||||
(id) => !currentTestIds.includes(id) && !removed.includes(id)
|
||||
)
|
||||
// Tests to remove: in removedTests
|
||||
const toRemove = removed.filter((id) => currentTestIds.includes(id))
|
||||
|
||||
if (toAdd.length > 0 || toRemove.length > 0) {
|
||||
onTestsChange(toAdd, toRemove)
|
||||
} else if (selectedTests.size > 0 || removedTests.size > 0) {
|
||||
// Also notify if selection was cleared
|
||||
onTestsChange([], [])
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedTests.size, removedTests.size, currentTestIds.join(',')])
|
||||
|
||||
const handleToggleTest = (testId: string) => {
|
||||
if (disabled || !testId) return
|
||||
|
||||
const testIdStr = String(testId)
|
||||
const isCurrentlySelected = selectedTests.has(testIdStr) && !removedTests.has(testIdStr)
|
||||
const isInCurrentPack = currentTestIds.includes(testIdStr)
|
||||
|
||||
if (isCurrentlySelected) {
|
||||
// Deselect test
|
||||
const newSelected = new Set(selectedTests)
|
||||
newSelected.delete(testIdStr)
|
||||
setSelectedTests(newSelected)
|
||||
|
||||
// If it was in current pack, mark as removed
|
||||
if (isInCurrentPack) {
|
||||
setRemovedTests((prev) => new Set([...prev, testIdStr]))
|
||||
}
|
||||
} else {
|
||||
// Select test
|
||||
const newSelected = new Set(selectedTests)
|
||||
newSelected.add(testIdStr)
|
||||
setSelectedTests(newSelected)
|
||||
|
||||
// If it was marked as removed, unmark it
|
||||
if (removedTests.has(testIdStr)) {
|
||||
setRemovedTests((prev) => {
|
||||
const newRemoved = new Set(prev)
|
||||
newRemoved.delete(testIdStr)
|
||||
return newRemoved
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isTestSelected = (testId: string | number) => {
|
||||
const testIdStr = String(testId)
|
||||
return selectedTests.has(testIdStr) && !removedTests.has(testIdStr)
|
||||
}
|
||||
|
||||
const isTestInCurrentPack = (testId: string | number) => {
|
||||
return currentTestIds.includes(String(testId))
|
||||
}
|
||||
|
||||
const allTests = testsData?.items || []
|
||||
const filteredTests = search
|
||||
? allTests.filter(
|
||||
(test) =>
|
||||
test.name?.toLowerCase().includes(search.toLowerCase()) ||
|
||||
test.id?.toLowerCase().includes(search.toLowerCase())
|
||||
)
|
||||
: allTests
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Manage Tests in Pack</Label>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Search className="h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="Search tests by name or ID..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
className="max-w-sm"
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Selected tests: {selectedTests.size - removedTests.size} / {allTests.length}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="text-center py-4">Loading tests...</div>
|
||||
) : (
|
||||
<div className="border rounded-lg max-h-[400px] overflow-y-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-12"></TableHead>
|
||||
<TableHead>ID</TableHead>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Questions</TableHead>
|
||||
<TableHead>Version</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredTests.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center text-muted-foreground">
|
||||
No tests found
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
filteredTests
|
||||
.filter((test) => test.id) // Only show tests with IDs
|
||||
.map((test) => {
|
||||
const testIdStr = String(test.id!)
|
||||
const selected = isTestSelected(testIdStr)
|
||||
const inCurrentPack = isTestInCurrentPack(testIdStr)
|
||||
const newlyRemoved = removedTests.has(testIdStr)
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
key={test.id}
|
||||
className={selected ? 'bg-muted/50' : ''}
|
||||
onClick={() => handleToggleTest(testIdStr)}
|
||||
>
|
||||
<TableCell>
|
||||
{selected ? (
|
||||
<Check className="h-4 w-4 text-primary" />
|
||||
) : (
|
||||
<div className="h-4 w-4 border rounded" />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="font-mono text-sm">{test.id || '-'}</TableCell>
|
||||
<TableCell className="font-medium">{test.name}</TableCell>
|
||||
<TableCell>
|
||||
{typeof test.questions === 'number'
|
||||
? test.questions
|
||||
: test.questions?.length || 0}
|
||||
</TableCell>
|
||||
<TableCell>{test.version || 'N/A'}</TableCell>
|
||||
<TableCell>
|
||||
{newlyRemoved ? (
|
||||
<Badge variant="destructive">Removed</Badge>
|
||||
) : selected && inCurrentPack ? (
|
||||
<Badge variant="default">In Pack</Badge>
|
||||
) : selected ? (
|
||||
<Badge variant="secondary">Selected</Badge>
|
||||
) : inCurrentPack ? (
|
||||
<Badge variant="outline">In Pack</Badge>
|
||||
) : null}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ import { Textarea } from '@/components/ui/textarea'
|
|||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { ImageUpload } from '@/components/ui/image-upload'
|
||||
import { PackCardsManager } from '@/components/PackCardsManager'
|
||||
import { PackTestsManager } from '@/components/PackTestsManager'
|
||||
import { Plus, Search, Edit, Trash2, ChevronLeft, ChevronRight } from 'lucide-react'
|
||||
|
||||
export default function PacksPage() {
|
||||
|
|
@ -72,6 +73,11 @@ export default function PacksPage() {
|
|||
const [cardsToAdd, setCardsToAdd] = useState<string[]>([])
|
||||
const [cardsToRemove, setCardsToRemove] = useState<string[]>([])
|
||||
|
||||
// Test management state
|
||||
const [currentTestIds, setCurrentTestIds] = useState<string[]>([])
|
||||
const [testsToAdd, setTestsToAdd] = useState<string[]>([])
|
||||
const [testsToRemove, setTestsToRemove] = useState<string[]>([])
|
||||
|
||||
const limit = 20
|
||||
|
||||
// Fetch packs
|
||||
|
|
@ -157,6 +163,9 @@ export default function PacksPage() {
|
|||
setCurrentCardIds([])
|
||||
setCardsToAdd([])
|
||||
setCardsToRemove([])
|
||||
setCurrentTestIds([])
|
||||
setTestsToAdd([])
|
||||
setTestsToRemove([])
|
||||
setIsDialogOpen(true)
|
||||
}
|
||||
|
||||
|
|
@ -184,6 +193,13 @@ export default function PacksPage() {
|
|||
setCurrentCardIds(cardIds)
|
||||
setCardsToAdd([])
|
||||
setCardsToRemove([])
|
||||
|
||||
// Initialize current test IDs from addTestIds (which contains all tests in pack)
|
||||
const testIds = fullPack.addTestIds?.map((id) => id.toString()) || []
|
||||
setCurrentTestIds(testIds)
|
||||
setTestsToAdd([])
|
||||
setTestsToRemove([])
|
||||
|
||||
setIsDialogOpen(true)
|
||||
} catch (error) {
|
||||
const errorMessage = isPacksApiError(error)
|
||||
|
|
@ -200,6 +216,9 @@ export default function PacksPage() {
|
|||
setCurrentCardIds([])
|
||||
setCardsToAdd([])
|
||||
setCardsToRemove([])
|
||||
setCurrentTestIds([])
|
||||
setTestsToAdd([])
|
||||
setTestsToRemove([])
|
||||
}
|
||||
|
||||
const handleCardsChange = (addIds: string[], removeIds: string[]) => {
|
||||
|
|
@ -207,6 +226,11 @@ export default function PacksPage() {
|
|||
setCardsToRemove(removeIds)
|
||||
}
|
||||
|
||||
const handleTestsChange = (addIds: string[], removeIds: string[]) => {
|
||||
setTestsToAdd(addIds)
|
||||
setTestsToRemove(removeIds)
|
||||
}
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
|
|
@ -233,6 +257,8 @@ export default function PacksPage() {
|
|||
cover: formData.cover || undefined,
|
||||
addCardIds: cardsToAdd.length > 0 ? cardsToAdd : undefined,
|
||||
removeCardIds: cardsToRemove.length > 0 ? cardsToRemove : undefined,
|
||||
addTestIds: testsToAdd.length > 0 ? testsToAdd : undefined,
|
||||
removeTestIds: testsToRemove.length > 0 ? testsToRemove : undefined,
|
||||
}
|
||||
|
||||
if (selectedPack) {
|
||||
|
|
@ -589,13 +615,22 @@ export default function PacksPage() {
|
|||
</div>
|
||||
|
||||
{selectedPack && (
|
||||
<div className="space-y-2">
|
||||
<PackCardsManager
|
||||
currentCardIds={currentCardIds}
|
||||
onCardsChange={handleCardsChange}
|
||||
disabled={createMutation.isPending || updateMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<PackCardsManager
|
||||
currentCardIds={currentCardIds}
|
||||
onCardsChange={handleCardsChange}
|
||||
disabled={createMutation.isPending || updateMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<PackTestsManager
|
||||
currentTestIds={currentTestIds}
|
||||
onTestsChange={handleTestsChange}
|
||||
disabled={createMutation.isPending || updateMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ export default function TestsPage() {
|
|||
<TableRow>
|
||||
<TableHead>ID</TableHead>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Packs</TableHead>
|
||||
<TableHead>Questions</TableHead>
|
||||
<TableHead>Version</TableHead>
|
||||
<TableHead>Time</TableHead>
|
||||
|
|
@ -323,6 +324,22 @@ export default function TestsPage() {
|
|||
<TableRow key={test.id || Math.random()}>
|
||||
<TableCell className="font-mono text-sm">{test.id || 'N/A'}</TableCell>
|
||||
<TableCell className="font-medium">{test.name}</TableCell>
|
||||
<TableCell>
|
||||
{test.packs && test.packs.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{test.packs.map((pack) => (
|
||||
<span
|
||||
key={pack.id}
|
||||
className="inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200"
|
||||
>
|
||||
{pack.title}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-muted-foreground text-sm">No packs</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{typeof test.questions === 'number'
|
||||
? test.questions
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ export interface GameCardDto {
|
|||
transcriptionMnemo?: string
|
||||
imageBack?: string
|
||||
back?: string
|
||||
createdAt?: string
|
||||
updatedAt?: string
|
||||
}
|
||||
|
||||
export interface EditCardPackDto {
|
||||
|
|
@ -173,6 +175,11 @@ import type { Question } from './questions'
|
|||
|
||||
export type TestQuestion = Question
|
||||
|
||||
export interface TestPackInfo {
|
||||
id: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export interface TestDto {
|
||||
id?: string
|
||||
name: string
|
||||
|
|
@ -183,4 +190,5 @@ export interface TestDto {
|
|||
timeSubtitle?: string
|
||||
questions: Question[]
|
||||
statistics?: unknown
|
||||
packs?: TestPackInfo[]
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -182,6 +182,10 @@ class AdminPacksApiV2 {
|
|||
final previewCards = await _db.packDao.getPreviewCards(packId);
|
||||
final previewCardIds = previewCards.map((c) => c.id).toList();
|
||||
|
||||
// Get tests for this pack
|
||||
final packTests = await _db.testDao.getTestsByPackId(packId);
|
||||
final testIds = packTests.map((t) => t.id).toList();
|
||||
|
||||
// Create EditCardPackDto
|
||||
final editDto = EditCardPackDto(
|
||||
id: pack.id,
|
||||
|
|
@ -199,7 +203,7 @@ class AdminPacksApiV2 {
|
|||
version: pack.version,
|
||||
order: pack.order,
|
||||
addCardIds: cards.map((c) => c.id).toList(),
|
||||
addTestIds: null,
|
||||
addTestIds: testIds,
|
||||
removeCardIds: null,
|
||||
removeTestIds: null,
|
||||
cardsOrder: cardsOrder,
|
||||
|
|
@ -350,6 +354,49 @@ class AdminPacksApiV2 {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle test associations if provided
|
||||
if (editDto.addTestIds != null && editDto.addTestIds!.isNotEmpty) {
|
||||
try {
|
||||
for (final testId in editDto.addTestIds!) {
|
||||
// Verify test exists before adding
|
||||
final test = await _db.testDao.getTestById(testId);
|
||||
if (test == null) {
|
||||
return _json(
|
||||
{
|
||||
'error': 'Test not found',
|
||||
'message': 'One of the tests you are trying to add does not exist',
|
||||
'field': 'addTestIds',
|
||||
'details': 'Test with ID "$testId" was not found. Please verify all test IDs before adding them to the pack.',
|
||||
},
|
||||
statusCode: 404,
|
||||
);
|
||||
}
|
||||
await _db.testDao.linkTestToPack(testId, packId);
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle duplicate or constraint errors
|
||||
if (e.toString().toLowerCase().contains('unique') ||
|
||||
e.toString().toLowerCase().contains('constraint')) {
|
||||
return _json(
|
||||
{
|
||||
'error': 'Duplicate test',
|
||||
'message': 'One or more tests are already in this pack',
|
||||
'field': 'addTestIds',
|
||||
'details': 'Some tests you are trying to add are already associated with this pack. Please remove duplicates and try again.',
|
||||
},
|
||||
statusCode: 409,
|
||||
);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
if (editDto.removeTestIds != null && editDto.removeTestIds!.isNotEmpty) {
|
||||
for (final testId in editDto.removeTestIds!) {
|
||||
await _db.testDao.unlinkTestFromPack(testId, packId);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle cards order if provided
|
||||
if (editDto.cardsOrder != null && editDto.cardsOrder!.isNotEmpty) {
|
||||
await _db.packDao.updatePackCardsOrder(
|
||||
|
|
@ -379,6 +426,10 @@ class AdminPacksApiV2 {
|
|||
final cardsOrder = updatedCards.map((c) => c.id).toList();
|
||||
final previewCards = await _db.packDao.getPreviewCards(packId);
|
||||
final previewCardIds = previewCards.map((c) => c.id).toList();
|
||||
|
||||
// Get updated tests for this pack
|
||||
final updatedPackTests = await _db.testDao.getTestsByPackId(packId);
|
||||
final updatedTestIds = updatedPackTests.map((t) => t.id).toList();
|
||||
|
||||
final updatedDto = EditCardPackDto(
|
||||
id: updatedPack.id,
|
||||
|
|
@ -396,7 +447,7 @@ class AdminPacksApiV2 {
|
|||
version: updatedPack.version,
|
||||
order: updatedPack.order,
|
||||
addCardIds: updatedCards.map((c) => c.id).toList(),
|
||||
addTestIds: null,
|
||||
addTestIds: updatedTestIds,
|
||||
removeCardIds: null,
|
||||
removeTestIds: null,
|
||||
cardsOrder: cardsOrder,
|
||||
|
|
|
|||
|
|
@ -119,6 +119,20 @@ class AdminTestsApiV2 {
|
|||
final testDtos = <Map<String, dynamic>>[];
|
||||
for (final test in allTests) {
|
||||
final questions = await _db.testDao.getTestQuestions(test.id);
|
||||
|
||||
// Get pack information for this test
|
||||
final packIds = await _db.testDao.getPackIdsForTest(test.id);
|
||||
final packs = <Map<String, dynamic>>[];
|
||||
for (final packId in packIds) {
|
||||
final pack = await _db.packDao.getPackById(packId);
|
||||
if (pack != null) {
|
||||
packs.add({
|
||||
'id': pack.id,
|
||||
'title': pack.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
testDtos.add({
|
||||
'id': test.id,
|
||||
'name': test.name,
|
||||
|
|
@ -128,6 +142,7 @@ class AdminTestsApiV2 {
|
|||
'time': test.time,
|
||||
'timeSubtitle': test.timeSubtitle,
|
||||
'questions': questions.length,
|
||||
'packs': packs,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -201,8 +216,21 @@ class AdminTestsApiV2 {
|
|||
);
|
||||
}
|
||||
|
||||
// Get packId for the test to build image URLs
|
||||
// Get packId for the test to build image URLs (use first pack if multiple)
|
||||
final packId = await _db.testDao.getPackIdForTest(testId);
|
||||
|
||||
// Get all pack information for this test
|
||||
final packIds = await _db.testDao.getPackIdsForTest(testId);
|
||||
final packs = <Map<String, dynamic>>[];
|
||||
for (final packIdItem in packIds) {
|
||||
final pack = await _db.packDao.getPackById(packIdItem);
|
||||
if (pack != null) {
|
||||
packs.add({
|
||||
'id': pack.id,
|
||||
'title': pack.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get questions
|
||||
final questions = await _db.testDao.getTestQuestions(testId);
|
||||
|
|
@ -319,6 +347,7 @@ class AdminTestsApiV2 {
|
|||
'time': test.time,
|
||||
'timeSubtitle': test.timeSubtitle,
|
||||
'questions': questionsWithUrls,
|
||||
'packs': packs,
|
||||
});
|
||||
} catch (e, s) {
|
||||
print('Error in getTest: $e\n$s');
|
||||
|
|
|
|||
|
|
@ -678,12 +678,6 @@ class PacksApiV2 {
|
|||
return _notFound('Pack not found');
|
||||
}
|
||||
|
||||
// Get cards for pack
|
||||
final cards = await _packManager.getCards(packId);
|
||||
if (cards.isEmpty) {
|
||||
return _notFound('Pack is empty');
|
||||
}
|
||||
|
||||
// Get tests for pack - fetchPackTests needs CardPackModel, but we can create a minimal one
|
||||
// or modify TestManager to work with Drift CardPack
|
||||
// For now, let's get tests directly from database
|
||||
|
|
|
|||
|
|
@ -71,6 +71,13 @@ class TestDao extends DatabaseAccessor<AppDatabase> with _$TestDaoMixin {
|
|||
);
|
||||
}
|
||||
|
||||
/// Удалить связь теста с паком
|
||||
Future<void> unlinkTestFromPack(String testId, String packId) async {
|
||||
await (delete(testPackRelations)
|
||||
..where((tpr) => tpr.testId.equals(testId) & tpr.packId.equals(packId))
|
||||
).go();
|
||||
}
|
||||
|
||||
/// Получить packId для теста
|
||||
Future<String?> getPackIdForTest(String testId) async {
|
||||
final relation = await (select(testPackRelations)
|
||||
|
|
@ -79,6 +86,14 @@ class TestDao extends DatabaseAccessor<AppDatabase> with _$TestDaoMixin {
|
|||
).getSingleOrNull();
|
||||
return relation?.packId;
|
||||
}
|
||||
|
||||
/// Получить все packId для теста
|
||||
Future<List<String>> getPackIdsForTest(String testId) async {
|
||||
final relations = await (select(testPackRelations)
|
||||
..where((tpr) => tpr.testId.equals(testId))
|
||||
).get();
|
||||
return relations.map((r) => r.packId).toList();
|
||||
}
|
||||
|
||||
// ==================== TestQuestions ====================
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,18 @@ export 'src/dtos/game_tests/test_question_type.dart';
|
|||
|
||||
export 'src/dtos/items/items.dart';
|
||||
|
||||
// Admin API models
|
||||
export 'src/dtos/admin/create_card_request.dart';
|
||||
export 'src/dtos/admin/create_card_response.dart';
|
||||
export 'src/dtos/admin/add_voice_request.dart';
|
||||
export 'src/dtos/admin/admin_voice_response.dart';
|
||||
export 'src/dtos/admin/voice_list_response.dart';
|
||||
export 'src/dtos/admin/success_response.dart';
|
||||
|
||||
// Common models
|
||||
export 'src/dtos/common/paginated_response.dart';
|
||||
export 'src/dtos/common/error_response.dart';
|
||||
|
||||
export 'src/utils/utils.dart';
|
||||
export 'src/utils/iterable_helper.dart';
|
||||
export 'src/utils/token_generator.dart';
|
||||
|
|
|
|||
25
mnemo_cards_common/lib/src/dtos/admin/add_voice_request.dart
Normal file
25
mnemo_cards_common/lib/src/dtos/admin/add_voice_request.dart
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
|
||||
part 'add_voice_request.g.dart';
|
||||
|
||||
/// Запрос для добавления голоса к карточке
|
||||
@JsonSerializable()
|
||||
@CopyWith()
|
||||
class AddVoiceRequest {
|
||||
/// URL голоса (base64 encoded audio data)
|
||||
final String voiceUrl;
|
||||
|
||||
/// Язык голоса (по умолчанию 'en')
|
||||
final String? language;
|
||||
|
||||
const AddVoiceRequest({
|
||||
required this.voiceUrl,
|
||||
this.language,
|
||||
});
|
||||
|
||||
factory AddVoiceRequest.fromJson(Map<String, dynamic> json) =>
|
||||
_$AddVoiceRequestFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$AddVoiceRequestToJson(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'add_voice_request.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$AddVoiceRequestCWProxy {
|
||||
AddVoiceRequest voiceUrl(String voiceUrl);
|
||||
|
||||
AddVoiceRequest language(String? language);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `AddVoiceRequest(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// AddVoiceRequest(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
AddVoiceRequest call({String voiceUrl, String? language});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfAddVoiceRequest.copyWith(...)` or call `instanceOfAddVoiceRequest.copyWith.fieldName(value)` for a single field.
|
||||
class _$AddVoiceRequestCWProxyImpl implements _$AddVoiceRequestCWProxy {
|
||||
const _$AddVoiceRequestCWProxyImpl(this._value);
|
||||
|
||||
final AddVoiceRequest _value;
|
||||
|
||||
@override
|
||||
AddVoiceRequest voiceUrl(String voiceUrl) => call(voiceUrl: voiceUrl);
|
||||
|
||||
@override
|
||||
AddVoiceRequest language(String? language) => call(language: language);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `AddVoiceRequest(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// AddVoiceRequest(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
AddVoiceRequest call({
|
||||
Object? voiceUrl = const $CopyWithPlaceholder(),
|
||||
Object? language = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return AddVoiceRequest(
|
||||
voiceUrl: voiceUrl == const $CopyWithPlaceholder() || voiceUrl == null
|
||||
? _value.voiceUrl
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: voiceUrl as String,
|
||||
language: language == const $CopyWithPlaceholder()
|
||||
? _value.language
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: language as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $AddVoiceRequestCopyWith on AddVoiceRequest {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfAddVoiceRequest.copyWith(...)` or `instanceOfAddVoiceRequest.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$AddVoiceRequestCWProxy get copyWith => _$AddVoiceRequestCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
AddVoiceRequest _$AddVoiceRequestFromJson(Map<String, dynamic> json) =>
|
||||
AddVoiceRequest(
|
||||
voiceUrl: json['voiceUrl'] as String,
|
||||
language: json['language'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AddVoiceRequestToJson(AddVoiceRequest instance) =>
|
||||
<String, dynamic>{
|
||||
'voiceUrl': instance.voiceUrl,
|
||||
'language': instance.language,
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
|
||||
part 'admin_voice_response.g.dart';
|
||||
|
||||
/// Ответ с данными голоса для admin API
|
||||
@JsonSerializable()
|
||||
@CopyWith()
|
||||
class AdminVoiceResponse {
|
||||
final String id;
|
||||
final String cardId;
|
||||
final String voiceUrl;
|
||||
final String language;
|
||||
final String createdAt;
|
||||
|
||||
const AdminVoiceResponse({
|
||||
required this.id,
|
||||
required this.cardId,
|
||||
required this.voiceUrl,
|
||||
required this.language,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory AdminVoiceResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$AdminVoiceResponseFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$AdminVoiceResponseToJson(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'admin_voice_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$AdminVoiceResponseCWProxy {
|
||||
AdminVoiceResponse id(String id);
|
||||
|
||||
AdminVoiceResponse cardId(String cardId);
|
||||
|
||||
AdminVoiceResponse voiceUrl(String voiceUrl);
|
||||
|
||||
AdminVoiceResponse language(String language);
|
||||
|
||||
AdminVoiceResponse createdAt(String createdAt);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `AdminVoiceResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// AdminVoiceResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
AdminVoiceResponse call({
|
||||
String id,
|
||||
String cardId,
|
||||
String voiceUrl,
|
||||
String language,
|
||||
String createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfAdminVoiceResponse.copyWith(...)` or call `instanceOfAdminVoiceResponse.copyWith.fieldName(value)` for a single field.
|
||||
class _$AdminVoiceResponseCWProxyImpl implements _$AdminVoiceResponseCWProxy {
|
||||
const _$AdminVoiceResponseCWProxyImpl(this._value);
|
||||
|
||||
final AdminVoiceResponse _value;
|
||||
|
||||
@override
|
||||
AdminVoiceResponse id(String id) => call(id: id);
|
||||
|
||||
@override
|
||||
AdminVoiceResponse cardId(String cardId) => call(cardId: cardId);
|
||||
|
||||
@override
|
||||
AdminVoiceResponse voiceUrl(String voiceUrl) => call(voiceUrl: voiceUrl);
|
||||
|
||||
@override
|
||||
AdminVoiceResponse language(String language) => call(language: language);
|
||||
|
||||
@override
|
||||
AdminVoiceResponse createdAt(String createdAt) => call(createdAt: createdAt);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `AdminVoiceResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// AdminVoiceResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
AdminVoiceResponse call({
|
||||
Object? id = const $CopyWithPlaceholder(),
|
||||
Object? cardId = const $CopyWithPlaceholder(),
|
||||
Object? voiceUrl = const $CopyWithPlaceholder(),
|
||||
Object? language = const $CopyWithPlaceholder(),
|
||||
Object? createdAt = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return AdminVoiceResponse(
|
||||
id: id == const $CopyWithPlaceholder() || id == null
|
||||
? _value.id
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: id as String,
|
||||
cardId: cardId == const $CopyWithPlaceholder() || cardId == null
|
||||
? _value.cardId
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: cardId as String,
|
||||
voiceUrl: voiceUrl == const $CopyWithPlaceholder() || voiceUrl == null
|
||||
? _value.voiceUrl
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: voiceUrl as String,
|
||||
language: language == const $CopyWithPlaceholder() || language == null
|
||||
? _value.language
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: language as String,
|
||||
createdAt: createdAt == const $CopyWithPlaceholder() || createdAt == null
|
||||
? _value.createdAt
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: createdAt as String,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $AdminVoiceResponseCopyWith on AdminVoiceResponse {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfAdminVoiceResponse.copyWith(...)` or `instanceOfAdminVoiceResponse.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$AdminVoiceResponseCWProxy get copyWith =>
|
||||
_$AdminVoiceResponseCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
AdminVoiceResponse _$AdminVoiceResponseFromJson(Map<String, dynamic> json) =>
|
||||
AdminVoiceResponse(
|
||||
id: json['id'] as String,
|
||||
cardId: json['cardId'] as String,
|
||||
voiceUrl: json['voiceUrl'] as String,
|
||||
language: json['language'] as String,
|
||||
createdAt: json['createdAt'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AdminVoiceResponseToJson(AdminVoiceResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'cardId': instance.cardId,
|
||||
'voiceUrl': instance.voiceUrl,
|
||||
'language': instance.language,
|
||||
'createdAt': instance.createdAt,
|
||||
};
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
|
||||
part 'create_card_request.g.dart';
|
||||
|
||||
/// Запрос для создания или обновления карточки
|
||||
/// Все поля optional для поддержки частичного обновления
|
||||
@JsonSerializable()
|
||||
@CopyWith()
|
||||
class CreateCardRequest {
|
||||
/// ID карточки. Если указан - это обновление существующей карточки
|
||||
final String? id;
|
||||
|
||||
/// ID пака для связи карточки с паком
|
||||
final String? packId;
|
||||
|
||||
/// Оригинальный текст (слово на иностранном языке)
|
||||
final String? original;
|
||||
|
||||
/// Перевод
|
||||
final String? translation;
|
||||
|
||||
/// Мнемоническая подсказка
|
||||
final String? mnemo;
|
||||
|
||||
/// Изображение (base64 или URL)
|
||||
final String? image;
|
||||
|
||||
/// Изображение на обратной стороне (base64 или URL)
|
||||
final String? imageBack;
|
||||
|
||||
/// Дополнительный текст на обратной стороне
|
||||
final String? back;
|
||||
|
||||
/// Транскрипция
|
||||
final String? transcription;
|
||||
|
||||
/// Транскрипция с мнемоникой
|
||||
final String? transcriptionMnemo;
|
||||
|
||||
const CreateCardRequest({
|
||||
this.id,
|
||||
this.packId,
|
||||
this.original,
|
||||
this.translation,
|
||||
this.mnemo,
|
||||
this.image,
|
||||
this.imageBack,
|
||||
this.back,
|
||||
this.transcription,
|
||||
this.transcriptionMnemo,
|
||||
});
|
||||
|
||||
factory CreateCardRequest.fromJson(Map<String, dynamic> json) =>
|
||||
_$CreateCardRequestFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$CreateCardRequestToJson(this);
|
||||
}
|
||||
194
mnemo_cards_common/lib/src/dtos/admin/create_card_request.g.dart
Normal file
194
mnemo_cards_common/lib/src/dtos/admin/create_card_request.g.dart
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'create_card_request.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$CreateCardRequestCWProxy {
|
||||
CreateCardRequest id(String? id);
|
||||
|
||||
CreateCardRequest packId(String? packId);
|
||||
|
||||
CreateCardRequest original(String? original);
|
||||
|
||||
CreateCardRequest translation(String? translation);
|
||||
|
||||
CreateCardRequest mnemo(String? mnemo);
|
||||
|
||||
CreateCardRequest image(String? image);
|
||||
|
||||
CreateCardRequest imageBack(String? imageBack);
|
||||
|
||||
CreateCardRequest back(String? back);
|
||||
|
||||
CreateCardRequest transcription(String? transcription);
|
||||
|
||||
CreateCardRequest transcriptionMnemo(String? transcriptionMnemo);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `CreateCardRequest(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// CreateCardRequest(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
CreateCardRequest call({
|
||||
String? id,
|
||||
String? packId,
|
||||
String? original,
|
||||
String? translation,
|
||||
String? mnemo,
|
||||
String? image,
|
||||
String? imageBack,
|
||||
String? back,
|
||||
String? transcription,
|
||||
String? transcriptionMnemo,
|
||||
});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfCreateCardRequest.copyWith(...)` or call `instanceOfCreateCardRequest.copyWith.fieldName(value)` for a single field.
|
||||
class _$CreateCardRequestCWProxyImpl implements _$CreateCardRequestCWProxy {
|
||||
const _$CreateCardRequestCWProxyImpl(this._value);
|
||||
|
||||
final CreateCardRequest _value;
|
||||
|
||||
@override
|
||||
CreateCardRequest id(String? id) => call(id: id);
|
||||
|
||||
@override
|
||||
CreateCardRequest packId(String? packId) => call(packId: packId);
|
||||
|
||||
@override
|
||||
CreateCardRequest original(String? original) => call(original: original);
|
||||
|
||||
@override
|
||||
CreateCardRequest translation(String? translation) =>
|
||||
call(translation: translation);
|
||||
|
||||
@override
|
||||
CreateCardRequest mnemo(String? mnemo) => call(mnemo: mnemo);
|
||||
|
||||
@override
|
||||
CreateCardRequest image(String? image) => call(image: image);
|
||||
|
||||
@override
|
||||
CreateCardRequest imageBack(String? imageBack) => call(imageBack: imageBack);
|
||||
|
||||
@override
|
||||
CreateCardRequest back(String? back) => call(back: back);
|
||||
|
||||
@override
|
||||
CreateCardRequest transcription(String? transcription) =>
|
||||
call(transcription: transcription);
|
||||
|
||||
@override
|
||||
CreateCardRequest transcriptionMnemo(String? transcriptionMnemo) =>
|
||||
call(transcriptionMnemo: transcriptionMnemo);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `CreateCardRequest(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// CreateCardRequest(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
CreateCardRequest call({
|
||||
Object? id = const $CopyWithPlaceholder(),
|
||||
Object? packId = const $CopyWithPlaceholder(),
|
||||
Object? original = const $CopyWithPlaceholder(),
|
||||
Object? translation = const $CopyWithPlaceholder(),
|
||||
Object? mnemo = const $CopyWithPlaceholder(),
|
||||
Object? image = const $CopyWithPlaceholder(),
|
||||
Object? imageBack = const $CopyWithPlaceholder(),
|
||||
Object? back = const $CopyWithPlaceholder(),
|
||||
Object? transcription = const $CopyWithPlaceholder(),
|
||||
Object? transcriptionMnemo = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return CreateCardRequest(
|
||||
id: id == const $CopyWithPlaceholder()
|
||||
? _value.id
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: id as String?,
|
||||
packId: packId == const $CopyWithPlaceholder()
|
||||
? _value.packId
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: packId as String?,
|
||||
original: original == const $CopyWithPlaceholder()
|
||||
? _value.original
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: original as String?,
|
||||
translation: translation == const $CopyWithPlaceholder()
|
||||
? _value.translation
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: translation as String?,
|
||||
mnemo: mnemo == const $CopyWithPlaceholder()
|
||||
? _value.mnemo
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: mnemo as String?,
|
||||
image: image == const $CopyWithPlaceholder()
|
||||
? _value.image
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: image as String?,
|
||||
imageBack: imageBack == const $CopyWithPlaceholder()
|
||||
? _value.imageBack
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: imageBack as String?,
|
||||
back: back == const $CopyWithPlaceholder()
|
||||
? _value.back
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: back as String?,
|
||||
transcription: transcription == const $CopyWithPlaceholder()
|
||||
? _value.transcription
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: transcription as String?,
|
||||
transcriptionMnemo: transcriptionMnemo == const $CopyWithPlaceholder()
|
||||
? _value.transcriptionMnemo
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: transcriptionMnemo as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $CreateCardRequestCopyWith on CreateCardRequest {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfCreateCardRequest.copyWith(...)` or `instanceOfCreateCardRequest.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$CreateCardRequestCWProxy get copyWith =>
|
||||
_$CreateCardRequestCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
CreateCardRequest _$CreateCardRequestFromJson(Map<String, dynamic> json) =>
|
||||
CreateCardRequest(
|
||||
id: json['id'] as String?,
|
||||
packId: json['packId'] as String?,
|
||||
original: json['original'] as String?,
|
||||
translation: json['translation'] as String?,
|
||||
mnemo: json['mnemo'] as String?,
|
||||
image: json['image'] as String?,
|
||||
imageBack: json['imageBack'] as String?,
|
||||
back: json['back'] as String?,
|
||||
transcription: json['transcription'] as String?,
|
||||
transcriptionMnemo: json['transcriptionMnemo'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CreateCardRequestToJson(CreateCardRequest instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'packId': instance.packId,
|
||||
'original': instance.original,
|
||||
'translation': instance.translation,
|
||||
'mnemo': instance.mnemo,
|
||||
'image': instance.image,
|
||||
'imageBack': instance.imageBack,
|
||||
'back': instance.back,
|
||||
'transcription': instance.transcription,
|
||||
'transcriptionMnemo': instance.transcriptionMnemo,
|
||||
};
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
import 'package:mnemo_cards_common/src/dtos/game_card_dto.dart';
|
||||
|
||||
part 'create_card_response.g.dart';
|
||||
|
||||
/// Ответ с созданной/обновленной карточкой
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
@CopyWith()
|
||||
class CreateCardResponse {
|
||||
final bool success;
|
||||
final GameCardDto card;
|
||||
|
||||
/// ID пака (первый из связанных паков, если есть)
|
||||
final String? packId;
|
||||
|
||||
const CreateCardResponse({
|
||||
required this.success,
|
||||
required this.card,
|
||||
this.packId,
|
||||
});
|
||||
|
||||
factory CreateCardResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$CreateCardResponseFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$CreateCardResponseToJson(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'create_card_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$CreateCardResponseCWProxy {
|
||||
CreateCardResponse success(bool success);
|
||||
|
||||
CreateCardResponse card(GameCardDto card);
|
||||
|
||||
CreateCardResponse packId(String? packId);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `CreateCardResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// CreateCardResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
CreateCardResponse call({bool success, GameCardDto card, String? packId});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfCreateCardResponse.copyWith(...)` or call `instanceOfCreateCardResponse.copyWith.fieldName(value)` for a single field.
|
||||
class _$CreateCardResponseCWProxyImpl implements _$CreateCardResponseCWProxy {
|
||||
const _$CreateCardResponseCWProxyImpl(this._value);
|
||||
|
||||
final CreateCardResponse _value;
|
||||
|
||||
@override
|
||||
CreateCardResponse success(bool success) => call(success: success);
|
||||
|
||||
@override
|
||||
CreateCardResponse card(GameCardDto card) => call(card: card);
|
||||
|
||||
@override
|
||||
CreateCardResponse packId(String? packId) => call(packId: packId);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `CreateCardResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// CreateCardResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
CreateCardResponse call({
|
||||
Object? success = const $CopyWithPlaceholder(),
|
||||
Object? card = const $CopyWithPlaceholder(),
|
||||
Object? packId = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return CreateCardResponse(
|
||||
success: success == const $CopyWithPlaceholder() || success == null
|
||||
? _value.success
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: success as bool,
|
||||
card: card == const $CopyWithPlaceholder() || card == null
|
||||
? _value.card
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: card as GameCardDto,
|
||||
packId: packId == const $CopyWithPlaceholder()
|
||||
? _value.packId
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: packId as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $CreateCardResponseCopyWith on CreateCardResponse {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfCreateCardResponse.copyWith(...)` or `instanceOfCreateCardResponse.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$CreateCardResponseCWProxy get copyWith =>
|
||||
_$CreateCardResponseCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
CreateCardResponse _$CreateCardResponseFromJson(Map<String, dynamic> json) =>
|
||||
CreateCardResponse(
|
||||
success: json['success'] as bool,
|
||||
card: GameCardDto.fromJson(json['card'] as Map<String, dynamic>),
|
||||
packId: json['packId'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CreateCardResponseToJson(CreateCardResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'success': instance.success,
|
||||
'card': instance.card.toJson(),
|
||||
'packId': instance.packId,
|
||||
};
|
||||
22
mnemo_cards_common/lib/src/dtos/admin/success_response.dart
Normal file
22
mnemo_cards_common/lib/src/dtos/admin/success_response.dart
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
|
||||
part 'success_response.g.dart';
|
||||
|
||||
/// Простой успешный ответ
|
||||
@JsonSerializable()
|
||||
@CopyWith()
|
||||
class SuccessResponse {
|
||||
final bool success;
|
||||
final String? message;
|
||||
|
||||
const SuccessResponse({
|
||||
required this.success,
|
||||
this.message,
|
||||
});
|
||||
|
||||
factory SuccessResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$SuccessResponseFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$SuccessResponseToJson(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'success_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$SuccessResponseCWProxy {
|
||||
SuccessResponse success(bool success);
|
||||
|
||||
SuccessResponse message(String? message);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `SuccessResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// SuccessResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
SuccessResponse call({bool success, String? message});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfSuccessResponse.copyWith(...)` or call `instanceOfSuccessResponse.copyWith.fieldName(value)` for a single field.
|
||||
class _$SuccessResponseCWProxyImpl implements _$SuccessResponseCWProxy {
|
||||
const _$SuccessResponseCWProxyImpl(this._value);
|
||||
|
||||
final SuccessResponse _value;
|
||||
|
||||
@override
|
||||
SuccessResponse success(bool success) => call(success: success);
|
||||
|
||||
@override
|
||||
SuccessResponse message(String? message) => call(message: message);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `SuccessResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// SuccessResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
SuccessResponse call({
|
||||
Object? success = const $CopyWithPlaceholder(),
|
||||
Object? message = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return SuccessResponse(
|
||||
success: success == const $CopyWithPlaceholder() || success == null
|
||||
? _value.success
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: success as bool,
|
||||
message: message == const $CopyWithPlaceholder()
|
||||
? _value.message
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: message as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $SuccessResponseCopyWith on SuccessResponse {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfSuccessResponse.copyWith(...)` or `instanceOfSuccessResponse.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$SuccessResponseCWProxy get copyWith => _$SuccessResponseCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SuccessResponse _$SuccessResponseFromJson(Map<String, dynamic> json) =>
|
||||
SuccessResponse(
|
||||
success: json['success'] as bool,
|
||||
message: json['message'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SuccessResponseToJson(SuccessResponse instance) =>
|
||||
<String, dynamic>{'success': instance.success, 'message': instance.message};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
import 'package:mnemo_cards_common/src/dtos/admin/admin_voice_response.dart';
|
||||
|
||||
part 'voice_list_response.g.dart';
|
||||
|
||||
/// Ответ со списком голосов
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
@CopyWith()
|
||||
class VoiceListResponse {
|
||||
final List<AdminVoiceResponse> items;
|
||||
|
||||
const VoiceListResponse({
|
||||
required this.items,
|
||||
});
|
||||
|
||||
factory VoiceListResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$VoiceListResponseFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$VoiceListResponseToJson(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'voice_list_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$VoiceListResponseCWProxy {
|
||||
VoiceListResponse items(List<AdminVoiceResponse> items);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `VoiceListResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// VoiceListResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
VoiceListResponse call({List<AdminVoiceResponse> items});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfVoiceListResponse.copyWith(...)` or call `instanceOfVoiceListResponse.copyWith.fieldName(value)` for a single field.
|
||||
class _$VoiceListResponseCWProxyImpl implements _$VoiceListResponseCWProxy {
|
||||
const _$VoiceListResponseCWProxyImpl(this._value);
|
||||
|
||||
final VoiceListResponse _value;
|
||||
|
||||
@override
|
||||
VoiceListResponse items(List<AdminVoiceResponse> items) => call(items: items);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `VoiceListResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// VoiceListResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
VoiceListResponse call({Object? items = const $CopyWithPlaceholder()}) {
|
||||
return VoiceListResponse(
|
||||
items: items == const $CopyWithPlaceholder() || items == null
|
||||
? _value.items
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: items as List<AdminVoiceResponse>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $VoiceListResponseCopyWith on VoiceListResponse {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfVoiceListResponse.copyWith(...)` or `instanceOfVoiceListResponse.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$VoiceListResponseCWProxy get copyWith =>
|
||||
_$VoiceListResponseCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
VoiceListResponse _$VoiceListResponseFromJson(Map<String, dynamic> json) =>
|
||||
VoiceListResponse(
|
||||
items: (json['items'] as List<dynamic>)
|
||||
.map((e) => AdminVoiceResponse.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$VoiceListResponseToJson(VoiceListResponse instance) =>
|
||||
<String, dynamic>{'items': instance.items.map((e) => e.toJson()).toList()};
|
||||
26
mnemo_cards_common/lib/src/dtos/common/error_response.dart
Normal file
26
mnemo_cards_common/lib/src/dtos/common/error_response.dart
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
|
||||
part 'error_response.g.dart';
|
||||
|
||||
/// Стандартизированный ответ об ошибке
|
||||
@JsonSerializable()
|
||||
@CopyWith()
|
||||
class ErrorResponse {
|
||||
final String error;
|
||||
final String message;
|
||||
final String? field;
|
||||
final String? details;
|
||||
|
||||
const ErrorResponse({
|
||||
required this.error,
|
||||
required this.message,
|
||||
this.field,
|
||||
this.details,
|
||||
});
|
||||
|
||||
factory ErrorResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$ErrorResponseFromJson(json);
|
||||
|
||||
Map<String, Object?> toJson() => _$ErrorResponseToJson(this);
|
||||
}
|
||||
112
mnemo_cards_common/lib/src/dtos/common/error_response.g.dart
Normal file
112
mnemo_cards_common/lib/src/dtos/common/error_response.g.dart
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'error_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$ErrorResponseCWProxy {
|
||||
ErrorResponse error(String error);
|
||||
|
||||
ErrorResponse message(String message);
|
||||
|
||||
ErrorResponse field(String? field);
|
||||
|
||||
ErrorResponse details(String? details);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `ErrorResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// ErrorResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
ErrorResponse call({
|
||||
String error,
|
||||
String message,
|
||||
String? field,
|
||||
String? details,
|
||||
});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfErrorResponse.copyWith(...)` or call `instanceOfErrorResponse.copyWith.fieldName(value)` for a single field.
|
||||
class _$ErrorResponseCWProxyImpl implements _$ErrorResponseCWProxy {
|
||||
const _$ErrorResponseCWProxyImpl(this._value);
|
||||
|
||||
final ErrorResponse _value;
|
||||
|
||||
@override
|
||||
ErrorResponse error(String error) => call(error: error);
|
||||
|
||||
@override
|
||||
ErrorResponse message(String message) => call(message: message);
|
||||
|
||||
@override
|
||||
ErrorResponse field(String? field) => call(field: field);
|
||||
|
||||
@override
|
||||
ErrorResponse details(String? details) => call(details: details);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `ErrorResponse(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// ErrorResponse(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
ErrorResponse call({
|
||||
Object? error = const $CopyWithPlaceholder(),
|
||||
Object? message = const $CopyWithPlaceholder(),
|
||||
Object? field = const $CopyWithPlaceholder(),
|
||||
Object? details = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return ErrorResponse(
|
||||
error: error == const $CopyWithPlaceholder() || error == null
|
||||
? _value.error
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: error as String,
|
||||
message: message == const $CopyWithPlaceholder() || message == null
|
||||
? _value.message
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: message as String,
|
||||
field: field == const $CopyWithPlaceholder()
|
||||
? _value.field
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: field as String?,
|
||||
details: details == const $CopyWithPlaceholder()
|
||||
? _value.details
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: details as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $ErrorResponseCopyWith on ErrorResponse {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfErrorResponse.copyWith(...)` or `instanceOfErrorResponse.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$ErrorResponseCWProxy get copyWith => _$ErrorResponseCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ErrorResponse _$ErrorResponseFromJson(Map<String, dynamic> json) =>
|
||||
ErrorResponse(
|
||||
error: json['error'] as String,
|
||||
message: json['message'] as String,
|
||||
field: json['field'] as String?,
|
||||
details: json['details'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ErrorResponseToJson(ErrorResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'error': instance.error,
|
||||
'message': instance.message,
|
||||
'field': instance.field,
|
||||
'details': instance.details,
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
|
||||
part 'paginated_response.g.dart';
|
||||
|
||||
/// Универсальный ответ с пагинацией
|
||||
@JsonSerializable(genericArgumentFactories: true)
|
||||
@CopyWith()
|
||||
class PaginatedResponse<T> {
|
||||
final List<T> items;
|
||||
final int total;
|
||||
final int page;
|
||||
final int limit;
|
||||
final int totalPages;
|
||||
|
||||
const PaginatedResponse({
|
||||
required this.items,
|
||||
required this.total,
|
||||
required this.page,
|
||||
required this.limit,
|
||||
required this.totalPages,
|
||||
});
|
||||
|
||||
factory PaginatedResponse.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
T Function(Object?) fromJsonT,
|
||||
) =>
|
||||
_$PaginatedResponseFromJson(json, fromJsonT);
|
||||
|
||||
Map<String, dynamic> toJson(Object? Function(T) toJsonT) =>
|
||||
_$PaginatedResponseToJson(this, toJsonT);
|
||||
}
|
||||
133
mnemo_cards_common/lib/src/dtos/common/paginated_response.g.dart
Normal file
133
mnemo_cards_common/lib/src/dtos/common/paginated_response.g.dart
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'paginated_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$PaginatedResponseCWProxy<T> {
|
||||
PaginatedResponse<T> items(List<T> items);
|
||||
|
||||
PaginatedResponse<T> total(int total);
|
||||
|
||||
PaginatedResponse<T> page(int page);
|
||||
|
||||
PaginatedResponse<T> limit(int limit);
|
||||
|
||||
PaginatedResponse<T> totalPages(int totalPages);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `PaginatedResponse<T>(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// PaginatedResponse<T>(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
PaginatedResponse<T> call({
|
||||
List<T> items,
|
||||
int total,
|
||||
int page,
|
||||
int limit,
|
||||
int totalPages,
|
||||
});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfPaginatedResponse.copyWith(...)` or call `instanceOfPaginatedResponse.copyWith.fieldName(value)` for a single field.
|
||||
class _$PaginatedResponseCWProxyImpl<T>
|
||||
implements _$PaginatedResponseCWProxy<T> {
|
||||
const _$PaginatedResponseCWProxyImpl(this._value);
|
||||
|
||||
final PaginatedResponse<T> _value;
|
||||
|
||||
@override
|
||||
PaginatedResponse<T> items(List<T> items) => call(items: items);
|
||||
|
||||
@override
|
||||
PaginatedResponse<T> total(int total) => call(total: total);
|
||||
|
||||
@override
|
||||
PaginatedResponse<T> page(int page) => call(page: page);
|
||||
|
||||
@override
|
||||
PaginatedResponse<T> limit(int limit) => call(limit: limit);
|
||||
|
||||
@override
|
||||
PaginatedResponse<T> totalPages(int totalPages) =>
|
||||
call(totalPages: totalPages);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `PaginatedResponse<T>(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// PaginatedResponse<T>(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
PaginatedResponse<T> call({
|
||||
Object? items = const $CopyWithPlaceholder(),
|
||||
Object? total = const $CopyWithPlaceholder(),
|
||||
Object? page = const $CopyWithPlaceholder(),
|
||||
Object? limit = const $CopyWithPlaceholder(),
|
||||
Object? totalPages = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return PaginatedResponse<T>(
|
||||
items: items == const $CopyWithPlaceholder() || items == null
|
||||
? _value.items
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: items as List<T>,
|
||||
total: total == const $CopyWithPlaceholder() || total == null
|
||||
? _value.total
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: total as int,
|
||||
page: page == const $CopyWithPlaceholder() || page == null
|
||||
? _value.page
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: page as int,
|
||||
limit: limit == const $CopyWithPlaceholder() || limit == null
|
||||
? _value.limit
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: limit as int,
|
||||
totalPages:
|
||||
totalPages == const $CopyWithPlaceholder() || totalPages == null
|
||||
? _value.totalPages
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: totalPages as int,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $PaginatedResponseCopyWith<T> on PaginatedResponse<T> {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfPaginatedResponse.copyWith(...)` or `instanceOfPaginatedResponse.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$PaginatedResponseCWProxy<T> get copyWith =>
|
||||
_$PaginatedResponseCWProxyImpl<T>(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PaginatedResponse<T> _$PaginatedResponseFromJson<T>(
|
||||
Map<String, dynamic> json,
|
||||
T Function(Object? json) fromJsonT,
|
||||
) => PaginatedResponse<T>(
|
||||
items: (json['items'] as List<dynamic>).map(fromJsonT).toList(),
|
||||
total: (json['total'] as num).toInt(),
|
||||
page: (json['page'] as num).toInt(),
|
||||
limit: (json['limit'] as num).toInt(),
|
||||
totalPages: (json['totalPages'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PaginatedResponseToJson<T>(
|
||||
PaginatedResponse<T> instance,
|
||||
Object? Function(T value) toJsonT,
|
||||
) => <String, dynamic>{
|
||||
'items': instance.items.map(toJsonT).toList(),
|
||||
'total': instance.total,
|
||||
'page': instance.page,
|
||||
'limit': instance.limit,
|
||||
'totalPages': instance.totalPages,
|
||||
};
|
||||
|
|
@ -738,20 +738,6 @@ class _CardSide extends StatelessWidget {
|
|||
return Image.network(
|
||||
imageUrl,
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) {
|
||||
return child;
|
||||
}
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
color: packColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Container(
|
||||
color: packColor.withOpacity(0.1),
|
||||
|
|
|
|||
Loading…
Reference in a new issue