How to refactor to create-t3-app?

I have the following setup. I have a Django backend and a Nextjs frontend. In Next, I replicate my Django models and have api functions for accessing the api endpoints from Django. How would I refactor this setup to an app that's created with create-t3-app Product/index.ts
export default class Product extends Base implements IProduct {
name: string;
description?: string;
brand?: IBrand;
bestseller: boolean;
type: string;
category?: ICategory | null;
lsExternalId?: string;
archived: boolean;
stockCount?: number;

constructor({
id = undefined,
createdAt = undefined,
updatedAt = undefined,

name,
description = undefined,
brand = undefined,
bestseller = false,
type,
category = undefined,
lsExternalId = undefined,
archived = false,
stockCount = undefined,
}: IBase & IProduct) {
super({ id, createdAt, updatedAt });

this.name = name;
this.description = description;
this.brand = new Brand({ ...brand });
this.bestseller = bestseller;
this.type = type;
this.category = category ? new Category({ ...category }) : undefined;
this.lsExternalId = lsExternalId;
this.archived = archived;
this.stockCount = stockCount;
}
}
export default class Product extends Base implements IProduct {
name: string;
description?: string;
brand?: IBrand;
bestseller: boolean;
type: string;
category?: ICategory | null;
lsExternalId?: string;
archived: boolean;
stockCount?: number;

constructor({
id = undefined,
createdAt = undefined,
updatedAt = undefined,

name,
description = undefined,
brand = undefined,
bestseller = false,
type,
category = undefined,
lsExternalId = undefined,
archived = false,
stockCount = undefined,
}: IBase & IProduct) {
super({ id, createdAt, updatedAt });

this.name = name;
this.description = description;
this.brand = new Brand({ ...brand });
this.bestseller = bestseller;
this.type = type;
this.category = category ? new Category({ ...category }) : undefined;
this.lsExternalId = lsExternalId;
this.archived = archived;
this.stockCount = stockCount;
}
}
26 Replies
niels
nielsOP•2y ago
Product/api.ts
export async function createProduct() {
return 'Not implemented';
}

export async function retrieveProduct() {
return 'Not implemented';
}

export async function updateProduct() {
return 'Not implemented';
}

export async function destroyProduct() {
return 'Not implemented';
}

export async function listProducts() {
const {
data: { results: products },
} = await api.get('/products/');

return products.map(
(product: any) =>
new Product({
id: product.id,
createdAt: product.created_at,
updatedAt: product.updated_at,

name: product.name,
description: product.description,
brand: new Brand({ ...product.brand }),
bestseller: product.bestseller,
type: product.type,
category: product.category
? new Category({ ...product.category })
: null,
lsExternalId: product.ls_external_id,
archived: product.archived,
stockCount: product.stock_count,
})
);
}
export async function createProduct() {
return 'Not implemented';
}

export async function retrieveProduct() {
return 'Not implemented';
}

export async function updateProduct() {
return 'Not implemented';
}

export async function destroyProduct() {
return 'Not implemented';
}

export async function listProducts() {
const {
data: { results: products },
} = await api.get('/products/');

return products.map(
(product: any) =>
new Product({
id: product.id,
createdAt: product.created_at,
updatedAt: product.updated_at,

name: product.name,
description: product.description,
brand: new Brand({ ...product.brand }),
bestseller: product.bestseller,
type: product.type,
category: product.category
? new Category({ ...product.category })
: null,
lsExternalId: product.ls_external_id,
archived: product.archived,
stockCount: product.stock_count,
})
);
}
Product/types.ts
export interface IProduct extends IBase {
name: string;
description?: string;
brand?: IBrand;
bestseller: boolean;
type: string;
category?: ICategory | null;
lsExternalId?: string;
archived: boolean;
stockCount?: number
}
export interface IProduct extends IBase {
name: string;
description?: string;
brand?: IBrand;
bestseller: boolean;
type: string;
category?: ICategory | null;
lsExternalId?: string;
archived: boolean;
stockCount?: number
}
Any help or advice is appreciated
Unknown User
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
niels
nielsOP•2y ago
Can/should I still use tRPC if I use Django's endpoints for fetching data
cje
cje•2y ago
maybe if you need to hide an api key or something otherwise probably not
niels
nielsOP•2y ago
Well currently we have an Axios client How does it differ from trpc
cje
cje•2y ago
trpc is for talking between your frontend and a typescript api that you own if you're not doing that then you don't have a use for it
niels
nielsOP•2y ago
Yeah no it's a Python Django backend What about Zod Is that still viable? In my stack My current stack basically is: Python Django backend Next frontend with; TypeScript Axios as API client NextAuth React-query Tailwind
cje
cje•2y ago
can you generate openapi definitions for your python project? that would allow you to import the api types in your frontend otherwise you can use zod schema and infer types from that
niels
nielsOP•2y ago
Not as of now no Not sure if that's easily implemented
cje
cje•2y ago
if you cant get that, then you basically just have to write types in the frontend manually which isnt great but tbh a lot of boomer company apps still work like that
niels
nielsOP•2y ago
Yeah thats what im currently doing I replicate my Django models one by one 💀
cje
cje•2y ago
then there's not much this stack can give you tbh you can use zod schema to validate forms etc but thats about it
niels
nielsOP•2y ago
Yeah thats what I thought
cje
cje•2y ago
i dont really understand axios, its like 12kb and all it does is make fetch syntax a bit nicer, but if bundle size isn't a big concern then i think your stack is fine as it is
niels
nielsOP•2y ago
I'd like to start using t3 for myself tho dont get me wrong Might look into Zod schemas and infering those into types then Do you have any general tips about the 'replicating' tho?
cje
cje•2y ago
Replace axios with a simple custom fetch wrapper
Axios can do a ton of stuff, but here's a simpler solution that can handle most use cases
niels
nielsOP•2y ago
I was thinking about refactoring my api.ts file to static methods for each replicated model So I would just have e.g. Product.create() instead of a createProduct fn
cje
cje•2y ago
i dont think that matters too much. if you prefer that syntax then go ahead tbh i usually give this sort of stuff to team members to decide
niels
nielsOP•2y ago
Is there any good practice for types
cje
cje•2y ago
so that i can put my foot down when theres a decision thats actually important to me
niels
nielsOP•2y ago
Hahah Yeah I kinda rolled into Tech Lead for these 2 projects im on At least for the Nextjs part
cje
cje•2y ago
just read the "basic usage" part here https://github.com/colinhacks/zod
GitHub
GitHub - colinhacks/zod: TypeScript-first schema validation with st...
TypeScript-first schema validation with static type inference - GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference
cje
cje•2y ago
for input types for the types of the API response theres not much you can do other than just write the type
niels
nielsOP•2y ago
Actually a nice read tho thanks I keep struggling on where to store all my types Kinda just all over the place rn Rather wondering if it's a better practice to keep it in a basic src/types directory and organise that by context instead It's personal preference in the end nonetheless But still
Unknown User
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
Want results from more Discord servers?
Add your server